This commit is contained in:
RichardG867
2020-03-24 19:10:49 -03:00
532 changed files with 26582 additions and 31166 deletions

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
src/*.o
src/*.exe
src/*.res
src/*.d
src/NUL

View File

@@ -31,7 +31,7 @@ Building
In order to compile 86Box from this repository, please follow this step-by-step
guide:
1. Install the [MSYS2](https://www.msys2.org/) environment. The rest of the guide will refer to the directory that you install it to (C:\msys32 or C:\msys64 by default) as the MSYS2 root.
2. Launch your MSYS2 environment using the `MSYS2 MinGW 32-bit` shortcut.
2. Launch your MSYS2 environment using the `MSYS2 MinGW 32-bit` shortcut. If you do not want to use the shortcut, launch it with `<MSYS2 root>\mingw32.exe`.
3. Once launched, run `pacman -Syu` in order to update the environment. You may need to do this twice, just follow the on-screen instructions. Make sure you re-run `pacman -Syu` periodically to keep the environment up-to-date.
4. Run the following command to install all of the dependencies: `pacman -S gdb make git mingw-w64-i686-toolchain mingw-w64-i686-openal mingw-w64-i686-freetype mingw-w64-i686-SDL2 mingw-w64-i686-zlib mingw-w64-i686-libpng mingw-w64-i686-ghostscript`. Additionally, you will need to download the developer's pack of WinPcap [from here](https://www.winpcap.org/devel.htm), and extract it into `<MSYS2 root>\mingw32\`.
5. Once the environment is fully updated and all dependencies are installed, `cd` into your cloned `86box\src`
@@ -46,7 +46,7 @@ guide:
8. In order to test your fresh build, replace the `86Box.exe` in your current
86Box enviroment with your freshly built one. If you do not have a
pre-existing 86Box environment, download the latest successful build from
http://ci.86box.net, and the ROM set from https://tinyurl.com/rs20191022.
http://ci.86box.net, and the latest ROM set from https://github.com/86Box/roms.
9. Enjoy using and testing the emulator! :)
If you encounter issues at any step or have additional questions, please join
@@ -75,4 +75,4 @@ Jenkins instance.
Donations
---------
We do not charge you for the emulator but donations are still welcome:
https://paypal.me/86Box .
https://paypal.me/86Box.

View File

@@ -8,13 +8,13 @@
*
* Main include file for the application.
*
* Version: @(#)86box.h 1.0.36 2019/12/05
* Version: @(#)86box.h 1.0.37 2020/01/19
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*f Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
*/
#ifndef EMU_86BOX_H
# define EMU_86BOX_H
@@ -74,6 +74,7 @@ extern int force_debug; /* (O) force debug output */
extern int video_fps; /* (O) render speed in fps */
#endif
extern int settings_only; /* (O) show only the settings dialog */
extern int no_quit_confirm; /* (O) do not ask for confirmation on quit */
#ifdef _WIN32
extern uint64_t unique_id;
extern uint64_t source_hwnd;
@@ -98,6 +99,7 @@ extern int vid_cga_contrast, /* (C) video */
gfxcard; /* (C) graphics/video card */
extern int serial_enabled[], /* (C) enable serial ports */
bugger_enabled, /* (C) enable ISAbugger */
postcard_enabled, /* (C) enable POST card */
isamem_type[], /* (C) enable ISA mem cards */
isartc_type; /* (C) enable ISA RTC card */
extern int sound_is_float, /* (C) sound uses FP values */
@@ -133,7 +135,7 @@ extern int serial_do_log;
extern int nic_do_log;
#endif
extern wchar_t exe_path[1024]; /* path (dir) of executable */
extern wchar_t exe_path[2048]; /* path (dir) of executable */
extern wchar_t usr_path[1024]; /* path (dir) of user data */
extern wchar_t cfg_path[1024]; /* full path of config file */
#ifndef USE_NEW_DYNAREC

View File

@@ -21,9 +21,9 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "cpu/cpu.h"
#include "cpu.h"
#include "device.h"
#include "io.h"
#include "86box_io.h"
typedef struct

View File

@@ -21,9 +21,9 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "cpu_new/cpu.h"
#include "cpu.h"
#include "device.h"
#include "io.h"
#include "86box_io.h"
typedef struct

View File

@@ -56,7 +56,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "io.h"
#include "86box_io.h"
#include "device.h"
#include "plat.h"
#include "ui.h"

View File

@@ -1,203 +0,0 @@
/************************************************************************
PCEM: IBM 5150 Cassette support
Copyright (C) 2019 John Elliott <seasip.webmaster@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../device.h"
#include "../cpu/cpu.h"
#include "../machine/machine.h"
#include "../ppi.h"
#include "../ui.h"
#include "../plat.h"
#include "pzx.h"
#include "cassette.h"
typedef struct cassette_t
{
uint8_t motor; /* Motor status */
pzxfile_t pzx;
int cycles_last; /* Cycle count at last cassette poll */
} cassette_t;
wchar_t cassettefn[256];
static cassette_t *st_cas;
#ifdef ENABLE_CASSETTE_LOG
int cassette_do_log = ENABLE_CASSETTE_LOG;
static void
cassette_log(const char *fmt, ...)
{
va_list ap;
if (cassette_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define cassette_log(fmt, ...)
#endif
/* The PCEM CPU uses IBM cycles (4.77MHz). PZX uses Spectrum cycles (3.5MHz)
* so scale accordingly. */
static int32_t
pzx_cycles(int32_t pc)
{
double d = pc;
return (int32_t)(((d * 3.5) / 4.772728) + 0.5);
}
void
cassette_eject(void)
{
if (st_cas->pzx.input) {
pzx_close(&st_cas->pzx);
}
cassettefn[0] = 0;
}
void
cassette_load(wchar_t *fn)
{
FILE *fp;
unsigned char magic[8];
if (!fn)
return;
fp = plat_fopen(fn, L"rb");
if (!fp) {
/* Warn user? */
cassette_log("Failed to open cassette input %s\n", fn);
return;
}
memset(magic, 0, sizeof(magic));
fread(magic, 1, sizeof(magic), fp);
/* Check for PZX signature. In due course support could be added for
* other formats like TZX */
if (!memcmp(magic, "PZXT", 4)) {
wchar_t *result;
result = pzx_open(&st_cas->pzx, fp);
if (result) {
cassette_log("Failed to open %s as PZX: %s\n",
fn, result);
fclose(fp);
return;
}
wcscpy(cassettefn, fn);
}
}
uint8_t
cassette_input(void)
{
int ticks;
/* While motor is off, result is loopback */
if (!st_cas->motor)
return ppispeakon;
/* If there is no tapefile open don't try to extract data */
if (st_cas->pzx.input == NULL)
return 0;
/* Otherwise see how many ticks there have been since the last input */
if (st_cas->cycles_last == -1)
st_cas->cycles_last = cycles;
if (cycles <= st_cas->cycles_last)
ticks = (st_cas->cycles_last - cycles);
else
ticks = (st_cas->cycles_last + (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed / 100) - cycles);
st_cas->cycles_last = cycles;
return pzx_advance(&st_cas->pzx, pzx_cycles(ticks));
}
void
cassette_set_motor(uint8_t on)
{
if (on && !st_cas->motor) {
cassette_log("Start cassette motor\n");
st_cas->cycles_last = -1;
}
if (st_cas->motor && !on) {
cassette_log("Stop cassette motor\n");
st_cas->cycles_last = -1;
}
st_cas->motor = on;
}
static void
*cassette_init(const device_t *info)
{
cassette_t *cas = (cassette_t *)malloc(sizeof(cassette_t));
memset(cas, 0, sizeof(cassette_t));
pzx_init(&cas->pzx);
st_cas = cas;
return cas;
}
static void
cassette_close(void *p)
{
cassette_t *cas = (cassette_t *)p;
pzx_close(&cas->pzx);
free(cas);
}
const device_t cassette_device = {
"IBM PC 5150 Cassette",
0,
0,
cassette_init,
cassette_close,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,30 +0,0 @@
/************************************************************************
PCEM: IBM 5150 cassette support
Copyright (C) 2019 John Elliott <seasip.webmaster@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*************************************************************************/
extern wchar_t cassettefn[256];
extern const device_t cassette_device;
uint8_t cassette_input(void);
void cassette_set_motor(uint8_t on);
void cassette_eject(void);
void cassette_load(wchar_t *filename);

View File

@@ -1,414 +0,0 @@
/************************************************************************
PCEM: IBM 5150 Cassette support
Copyright (C) 2019 John Elliott <seasip.webmaster@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../ui.h"
#include "pzx.h"
/* This module is intended to abstract all the details of a PZX file and
* emit its contents as a bitstream in a form suitable for PCEM. Similar
* modules could be written to add support for other tape formats such as TZX,
* TAP or CSW. */
#ifdef ENABLE_PZX_LOG
int pzx_do_log = ENABLE_PZX_LOG;
static void
pzx_log(const char *fmt, ...)
{
va_list ap;
if (pzx_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define pzx_log(fmt, ...)
#endif
static uint32_t
peek2(uint8_t *data)
{
return (((uint32_t)data[1]) << 8) | data[0];
}
static uint32_t
peek4(uint8_t *data)
{
return (((uint32_t)data[3]) << 24) |
(((uint32_t)data[2]) << 16) |
(((uint32_t)data[1]) << 8) | data[0];
}
/* Cue up the next pulse definition from the current PULS block. */
static void
pzx_parse_pulse(pzxfile_t *pzx)
{
pzx->puls_duration = peek2(pzx->curblock + pzx->puls_ptr);
pzx->puls_ptr += 2;
if (pzx->puls_duration > 0x8000) {
pzx->puls_count = pzx->puls_duration & 0x7FFF;
pzx->puls_duration = peek2(pzx->curblock + pzx->puls_ptr);
pzx->puls_ptr += 2;
}
if (pzx->puls_duration >= 0x8000) {
pzx->puls_duration &= 0x7FFF;
pzx->puls_duration <<= 16;
pzx->puls_duration |= peek2(pzx->curblock + pzx->puls_ptr);
pzx->puls_ptr += 2;
}
if (!pzx->puls_count) pzx->puls_count = 1;
}
void
pzx_init(pzxfile_t *pzx)
{
memset(pzx, 0, sizeof(pzxfile_t));
pzx->state = PZX_CLOSED;
}
/* Load the next block from a PZX-format file.
*
* Returns block if successful, NULL if end of file or error
* Caller must free the block with free(). */
uint8_t
*pzx_load_block(FILE *fp)
{
uint8_t block_header[8];
uint8_t *block_data;
uint32_t block_len;
/* The first 8 bytes of a PZX block are fixed: the first 4 give
* the ID, the second 4 the length (excluding the header itself) */
if (fread(block_header, 1, 8, fp) < 8)
return NULL; /* EoF */
block_len = peek4(block_header + 4);
block_data = malloc(8 + block_len);
if (!block_data) return NULL;
memcpy(block_data, block_header, 8);
if (!block_len) { /* Block is only the header */
/* CAS_LOG(("Loaded PZX block: %-4.4s\n", block_data)); */
return block_data;
}
if (fread(block_data + 8, 1, block_len, fp) < block_len) {
free(block_data); /* Unexpected EoF */
return NULL;
}
/* CAS_LOG(("Loaded PZX block: %-4.4s\n", block_data)); */
return block_data;
}
/* Search the current file for PZX version headers and check they're all 1.x */
static wchar_t
*pzx_check_version(FILE *fp)
{
uint8_t *block;
static wchar_t message[80];
rewind(fp);
while ((block = pzx_load_block(fp))) {
if (!memcmp(block, "PZXT", 4)) {
pzx_log("PZX version %d.%d\n", block[8], block[9]);
if (block[8] != 1) {
swprintf(message, 80, L"Unsupported PZX version %d.%d\n", block[8], block[9]);
free(block);
return message;
}
}
free(block);
}
rewind(fp);
return NULL;
}
wchar_t
*pzx_open(pzxfile_t *pzx, FILE *fp)
{
wchar_t *result;
rewind(fp);
/* Check that this file is compatible */
result = pzx_check_version(fp);
if (result)
return result;
pzx->level = 0;
pzx->state = PZX_IDLE;
pzx->input = fp;
return NULL;
}
void
pzx_close(pzxfile_t *pzx)
{
if (pzx->input) {
fclose(pzx->input);
pzx->input = NULL;
}
if (pzx->curblock) {
free(pzx->curblock);
pzx->curblock = NULL;
}
pzx->state = PZX_CLOSED;
}
/* Read the next block of type DATA, PAUS or PULS */
int
pzx_next_block(pzxfile_t *pzx)
{
long pos;
pos = ftell(pzx->input);
while (pzx->state == PZX_IDLE) {
uint8_t *blk;
/* In idle state there should be no current block. But
* make sure of that */
if (pzx->curblock) {
free(pzx->curblock);
pzx->curblock = NULL;
}
/* Load the next block */
blk = pzx_load_block(pzx->input);
/* If that didn't load we've reached the end of file; wrap to
* beginning. */
if (!blk) {
rewind(pzx->input);
blk = pzx_load_block(pzx->input);
if (!blk) { /* Couldn't even load first block */
pzx_close(pzx);
return 0;
}
/* Have we read the whole file and come back to where
* we were? */
if (ftell(pzx->input) == pos) {
free(blk);
pzx_close(pzx);
return 0;
}
}
/* We have loaded the next block. What is it? */
if (!memcmp(blk, "PULS", 4)) {
pzx->state = PZX_IN_PULS;
pzx->curblock = blk;
pzx->puls_len = 8 + peek4(blk + 4);
pzx->puls_ptr = 8;
pzx->puls_count = 0;
pzx->puls_remain = 0;
pzx->puls_duration = 0;
pzx->level = 0;
pzx_log("Beginning PULS block\n");
}
else if (!memcmp(blk, "PAUS", 4)) {
pzx->state = PZX_IN_PAUS;
pzx->curblock = blk;
pzx->paus_remain = peek4(blk + 8);
pzx->level = (pzx->paus_remain >> 31);
pzx->paus_remain &= 0x7FFFFFFF;
pzx_log("Beginning PAUS block, duration=%d\n",
pzx->paus_remain);
}
else if (!memcmp(blk, "DATA", 4)) {
pzx->state = PZX_IN_DATA;
pzx->curblock = blk;
pzx->data_bits = peek4(blk + 8);
pzx->level = (pzx->data_bits >> 31);
pzx->data_bits &= 0x7FFFFFFF;
pzx->data_tail = peek2(blk + 12);
pzx->data_p0 = blk[14];
pzx->data_p1 = blk[15];
pzx->data_p = 0;
pzx->data_w = 16;
pzx->data_remain = 0;
pzx->data_ptr = 16 + 2 * (pzx->data_p0 + pzx->data_p1);
pzx->data_mask = 0x80;
pzx_log("Beginning DATA block, length=%d p0=%d p1=%d"
" data_ptr=%d\n",
pzx->data_bits,
pzx->data_p0, pzx->data_p1,
pzx->data_ptr);
}
}
return 1;
}
static void
pzx_endblock(pzxfile_t *pzx)
{
if (pzx->curblock)
free(pzx->curblock);
pzx->curblock = NULL;
pzx->state = PZX_IDLE;
}
/* PAUS is easy - just run the timer down */
static int
pzx_advance_paus(pzxfile_t *pzx, int time)
{
if (pzx->paus_remain > time) {
pzx->paus_remain -= time;
return 0;
}
time -= pzx->paus_remain;
pzx_endblock(pzx);
return time;
}
static int
pzx_advance_puls(pzxfile_t *pzx, int time)
{
/* At the start of a pulse sequence? */
if (pzx->puls_count == 0) {
pzx_parse_pulse(pzx);
pzx->puls_remain = pzx->puls_duration;
}
/* Does sample trigger a pulse change? If not, that's easy. */
if (time < pzx->puls_remain) {
pzx->puls_remain -= time;
return 0;
}
/* Sample does trigger a pulse change */
time -= pzx->puls_remain;
/* If there's another pulse in the current sequence, that's
* straightforward; just flip the level and continue */
--pzx->puls_count;
pzx->level = !pzx->level;
if (pzx->puls_count) {
pzx->puls_remain = pzx->puls_duration;
return time;
}
/* If we've reached the end of the pulse sequence, there may be
* another one */
if (pzx->puls_ptr < pzx->puls_len) {
return time;
}
/* If there isn't another one, it's the end of the block */
pzx_endblock(pzx);
return time;
}
/* Decode a DATA block */
static int
pzx_advance_data(pzxfile_t *pzx, int time)
{
uint8_t bit;
/* Reached end of data? */
if (pzx->data_bits == 0) {
/* Time interval is covered by the tail bit */
if (pzx->data_tail > time) {
pzx->data_tail -= time;
return 0;
}
/* Have run out of block */
time -= pzx->data_tail;
pzx_endblock(pzx);
return time;
}
/* No more time remaining on the current bit? */
if (pzx->data_p < 1 && !pzx->data_remain) {
bit = pzx->curblock[pzx->data_ptr] & pzx->data_mask;
pzx->data_mask >>= 1;
if (!pzx->data_mask) {
pzx->data_mask = 0x80;
++pzx->data_ptr;
}
--pzx->data_bits;
if (bit) {
pzx->data_p = pzx->data_p1;
pzx->data_w = 16 + 2 * pzx->data_p0;
pzx->data_remain = 0;
} else {
pzx->data_p = pzx->data_p0;
pzx->data_w = 16;
pzx->data_remain = 0;
}
}
/* See if we've started processing the current waveform. If not,
* load its first element (assuming that there is one) */
if (!pzx->data_remain) {
if (pzx->data_p) {
pzx->data_remain = peek2(pzx->curblock + pzx->data_w);
pzx->data_w += 2;
pzx->data_p--;
}
}
if (pzx->data_remain > time) {
/* Time advance is contained within current wave */
pzx->data_remain -= time;
return 0;
} else { /* Move on to next element of wave / next bit / next block */
time -= pzx->data_remain;
pzx->data_remain = 0;
pzx->level = !pzx->level;
}
return time;
}
int
pzx_advance(pzxfile_t *pzx, int time)
{
if (pzx->state == PZX_CLOSED)
return 0; /* No tape loaded */
while (time) {
switch (pzx->state)
{
case PZX_IDLE:
if (!pzx_next_block(pzx)) return 0;
break;
case PZX_IN_PULS:
time = pzx_advance_puls(pzx, time);
break;
case PZX_IN_PAUS:
time = pzx_advance_paus(pzx, time);
break;
case PZX_IN_DATA:
time = pzx_advance_data(pzx, time);
break;
}
}
return pzx->level;
}

View File

@@ -1,71 +0,0 @@
/************************************************************************
PCEM: IBM 5150 cassette support
Copyright (C) 2019 John Elliott <seasip.webmaster@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*************************************************************************/
typedef enum
{
PZX_CLOSED, /* File is not open */
PZX_IDLE, /* File is open, no block loaded */
PZX_IN_PULS, /* File is open, current block is a PULS block */
PZX_IN_DATA, /* File is open, current block is a DATA block */
PZX_IN_PAUS, /* File is open, current block is a PAUS block */
} PZX_STATE;
typedef struct pzxfile_t
{
FILE *input; /* Input PZX file */
uint8_t *curblock; /* Currently-loaded block, if any */
int level; /* Current signal level */
PZX_STATE state; /* State machine current status */
/* State variables for PULS */
uint32_t puls_ptr; /* Pointer within PULS block */
uint32_t puls_len; /* Length of PULS block */
uint32_t puls_count; /* Count of pulses */
uint32_t puls_duration; /* Duration of each pulse */
uint32_t puls_remain; /* Time remaining in this pulse */
/* State variables for PAUS */
uint32_t paus_remain; /* Time remaining in this pause */
/* State variables for DATA */
uint32_t data_ptr; /* Pointer within DATA block */
uint32_t data_bits; /* Count of bits */
uint16_t data_tail; /* Length of pulse after last bit */
uint8_t data_mask; /* Mask for current bit */
uint8_t data_p0; /* Length of 0 encoding */
uint8_t data_p1; /* Length of 1 encoding */
int data_p; /* Current sequence being emitted */
uint32_t data_w; /* Current waveform */
uint32_t data_remain; /* Current data pulse time remaining */
} pzxfile_t;
uint8_t *pzx_load_block(FILE *fp);
/* Initialise structure */
void pzx_init(pzxfile_t *pzx);
/* Open file for input */
wchar_t *pzx_open(pzxfile_t *pzx, FILE *fp);
/* Close file */
void pzx_close(pzxfile_t *pzx);
/* Advance by 'time' samples (3.5MHz sample rate) and return current state */
int pzx_advance(pzxfile_t *pzx, int time);

View File

@@ -8,7 +8,7 @@
*
* Generic CD-ROM drive core.
*
* Version: @(#)cdrom.c 1.0.9 2019/12/13
* Version: @(#)cdrom.c 1.0.10 2020/03/23
*
* Author: Miran Grca, <mgrca8@gmail.com>
*
@@ -22,12 +22,12 @@
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../config.h"
#include "86box.h"
#include "config.h"
#include "cdrom.h"
#include "cdrom_image.h"
#include "../plat.h"
#include "../sound/sound.h"
#include "plat.h"
#include "sound.h"
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
@@ -41,6 +41,8 @@
#define MIN_SEEK 2000
#define MAX_SEEK 333333
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CD_DCB(x) ((((x) & 0xf0) >> 4) * 10 + ((x) & 0x0f))
#pragma pack(push,1)
typedef struct {
@@ -345,6 +347,72 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
return 1;
}
uint8_t
cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
{
int m = 0, s = 0, f = 0;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
switch (type) {
case 0x40:
cdrom_log("Audio Track Search: MSF = %06x, type = %02x\n", pos, type);
m = CD_DCB((pos >> 24) & 0xff);
s = CD_DCB((pos >> 16) & 0xff);
f = CD_DCB((pos >> 8) & 0xff);
pos = MSFtoLBA(m, s, f) - 150;
break;
}
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}
dev->seek_pos = pos;
dev->noplay = !playbit;
dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED;
return 1;
}
uint8_t
cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type)
{
int m = 0, s = 0, f = 0;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
if (dev->cd_status == CD_STATUS_STOPPED || dev->cd_status == CD_STATUS_PAUSED)
dev->cd_status = CD_STATUS_PLAYING;
/*Preliminary support, revert if too incomplete*/
switch (type) {
case 0x40:
cdrom_log("Toshiba Play Audio: MSF = %06x, type = %02x\n", pos, type);
m = CD_DCB((pos >> 24) & 0xff);
s = CD_DCB((pos >> 16) & 0xff);
f = CD_DCB((pos >> 8) & 0xff);
pos = MSFtoLBA(m, s, f) - 150;
break;
}
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}
dev->cd_end = pos;
dev->cd_buflen = 0;
return 1;
}
void
cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume)
@@ -409,6 +477,38 @@ cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf)
return ret;
}
uint8_t
cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
{
uint8_t ret;
subchannel_t subc;
dev->ops->get_subchannel(dev, dev->seek_pos, &subc);
if (dev->cd_status == CD_STATUS_PLAYING)
ret = 0x00;
else if (dev->cd_status == CD_STATUS_PAUSED) {
if (dev->noplay)
ret = 0x02;
else
ret = 0x01;
}
else
ret = 0x03;
b[0] = subc.attr;
b[1] = CD_BCD(subc.track);
b[2] = CD_BCD(subc.index);
b[3] = CD_BCD(subc.rel_m);
b[4] = CD_BCD(subc.rel_s);
b[5] = CD_BCD(subc.rel_f);
b[6] = CD_BCD(subc.abs_m);
b[7] = CD_BCD(subc.abs_s);
b[8] = CD_BCD(subc.abs_f);
cdrom_log("CD-ROM %i: Returned subcode-q at %02i:%02i.%02i, track=%02x\n", dev->id, b[3], b[4], b[5], b[1]);
return ret;
}
static int
read_toc_normal(cdrom_t *dev, unsigned char *b, unsigned char start_track, int msf)
@@ -557,6 +657,44 @@ cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type, unsigned char start_tra
return len;
}
void
cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type)
{
track_info_t ti;
int first_track, last_track;
dev->ops->get_tracks(dev, &first_track, &last_track);
switch (type) {
case 0:
b[0] = CD_BCD(first_track);
b[1] = CD_BCD(last_track);
b[2] = 0;
b[3] = 0;
break;
case 1:
dev->ops->get_track_info(dev, 0xAA, 0, &ti);
b[0] = CD_BCD(ti.m);
b[1] = CD_BCD(ti.s);
b[2] = CD_BCD(ti.f);
b[3] = 0;
break;
case 2:
dev->ops->get_track_info(dev, CD_DCB(track), 0, &ti);
b[0] = CD_BCD(ti.m);
b[1] = CD_BCD(ti.s);
b[2] = CD_BCD(ti.f);
b[3] = ti.attr;
cdrom_log("CD-ROM %i: Returned Toshiba disc information at %02i:%02i.%02i, track=%d\n", dev->id, b[0], b[1], b[2], CD_DCB(track));
break;
case 3:
b[0] = 0x00; /*TODO: correct it further, mark it as CD-Audio/CD-ROM disc for now*/
b[1] = 0;
b[2] = 0;
b[3] = 0;
break;
}
}
static int
track_type_is_valid(uint8_t id, int type, int flags, int audio, int mode2)

View File

@@ -112,7 +112,7 @@ typedef struct cdrom {
seek_diff, cd_end;
int host_drive, prev_host_drive,
cd_buflen;
cd_buflen, noplay;
const cdrom_ops_t *ops;
@@ -134,12 +134,17 @@ extern double cdrom_seek_time(cdrom_t *dev);
extern void cdrom_stop(cdrom_t *dev);
extern int cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len);
extern uint8_t cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf);
extern uint8_t cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit);
extern uint8_t cdrom_toshiba_audio_play(cdrom_t *dev, uint32_t pos, int type);
extern void cdrom_audio_pause_resume(cdrom_t *dev, uint8_t resume);
extern uint8_t cdrom_get_current_subchannel(cdrom_t *dev, uint8_t *b, int msf);
extern uint8_t cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b);
extern int cdrom_read_toc(cdrom_t *dev, unsigned char *b, int type,
unsigned char start_track, int msf, int max_len);
extern int cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, int sector, int ismsf,
int cdrom_sector_type, int cdrom_sector_flags, int *len);
extern void cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, int type);
extern void cdrom_seek(cdrom_t *dev, uint32_t pos);
extern void cdrom_close_handler(uint8_t id);

View File

@@ -21,6 +21,7 @@
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
@@ -28,10 +29,10 @@
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../config.h"
#include "../plat.h"
#include "../scsi/scsi_device.h"
#include "86box.h"
#include "config.h"
#include "plat.h"
#include "scsi_device.h"
#include "cdrom_image_backend.h"
#include "cdrom.h"
#include "cdrom_image.h"
@@ -113,18 +114,15 @@ image_get_capacity(cdrom_t *dev)
int first_track, last_track;
int number, c;
unsigned char attr;
TMSF tmsf;
uint32_t lb = 0;
uint32_t address;
uint32_t address = 0, lb = 0;
if (!img)
return 0;
cdi_get_audio_tracks(img, &first_track, &last_track, &tmsf);
cdi_get_audio_tracks_lba(img, &first_track, &last_track, &lb);
for (c = 0; c <= last_track; c++) {
cdi_get_audio_track_info(img, 0, c + 1, &number, &tmsf, &attr);
address = MSFtoLBA(tmsf.min, tmsf.sec, tmsf.fr) - 150; /* Do the - 150 here as well. */
cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr);
if (address > lb)
lb = address;
}
@@ -140,7 +138,7 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
uint8_t attr;
TMSF tmsf;
int m, s, f;
int number;
int number, track;
if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY))
return 0;
@@ -153,9 +151,13 @@ image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
}
/* GetTrack requires LBA. */
cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
track = cdi_get_track(img, pos);
if (track == -1)
return 0;
else {
cdi_get_audio_track_info(img, 0, cdi_get_track(img, pos), &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
}
}
@@ -276,7 +278,7 @@ cdrom_image_open(cdrom_t *dev, const wchar_t *fn)
dev->seek_pos = 0;
dev->cd_buflen = 0;
dev->cdrom_capacity = image_get_capacity(dev);
cdrom_image_log("CD-ROM capacity: %i sectors (%i bytes)\n", dev->cdrom_capacity, dev->cdrom_capacity << 11);
cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL);
/* Attach this handler to the drive. */
dev->ops = &cdrom_image_ops;

View File

@@ -9,7 +9,7 @@
* CD-ROM image file handling module, translated to C from
* cdrom_dosbox.cpp.
*
* Version: @(#)cdrom_image_backend.c 1.0.3 2020/01/13
* Version: @(#)cdrom_image_backend.c 1.0.5 2020/01/17
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -35,8 +35,8 @@
#endif
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../plat.h"
#include "86box.h"
#include "plat.h"
#include "cdrom_image_backend.h"
@@ -47,6 +47,9 @@
#define CROSS_LEN 512
static char temp_keyword[1024];
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG;
@@ -79,11 +82,16 @@ bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count)
if (tf->file == NULL)
return 0;
fseeko64(tf->file, seek, SEEK_SET);
if (fseeko64(tf->file, seek, SEEK_SET) == -1) {
#ifdef ENABLE_cdrom_image_backend_log
cdrom_image_backend_log("CDROM: binary_read failed during seek!\n");
#endif
return 0;
}
if (fread(buffer, count, 1, tf->file) != 1) {
#ifdef ENABLE_cdrom_image_backend_log
cdrom_image_backend_log("CDROM: binary_read failed!\n");
cdrom_image_backend_log("CDROM: binary_read failed during read!\n");
#endif
return 0;
}
@@ -136,14 +144,15 @@ bin_init(const wchar_t *filename, int *error)
track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t));
if (tf == NULL) {
tf->read = NULL;
tf->get_length = NULL;
tf->close = NULL;
*error = 1;
return NULL;
}
memset(tf->fn, 0x00, sizeof(tf->fn));
wcscpy(tf->fn, filename);
if (wcslen(filename) <= 260)
wcscpy(tf->fn, filename);
else
wcsncpy(tf->fn, filename, 260);
tf->file = plat_fopen64(tf->fn, L"rb");
cdrom_image_backend_log("CDROM: binary_open(%ls) = %08lx\n", tf->fn, tf->file);
@@ -157,9 +166,6 @@ bin_init(const wchar_t *filename, int *error)
} else {
free(tf);
tf = NULL;
tf->read = NULL;
tf->get_length = NULL;
tf->close = NULL;
}
return tf;
@@ -184,6 +190,9 @@ track_file_close(track_t *trk)
if (trk->file == NULL)
return;
if (trk->file->close == NULL)
return;
trk->file->close(trk->file);
trk->file = NULL;
}
@@ -203,10 +212,12 @@ cdi_clear_tracks(cd_img_t *cdi)
for (i = 0; i < cdi->tracks_num; i++) {
cur = &cdi->tracks[i];
/* Make sure we do not attempt to close a NULL file. */
if (cur->file != last) {
track_file_close(cur);
last = cur->file;
}
track_file_close(cur);
} else
cur->file = NULL;
}
/* Now free the array. */
@@ -251,6 +262,17 @@ cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out)
}
int
cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out)
{
*st_track = 1;
*end = cdi->tracks_num - 1;
*lead_out = cdi->tracks[*end].start;
return 1;
}
/* This replaces both Info and EndInfo, they are specified by a variable. */
int
cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr)
@@ -264,6 +286,24 @@ cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF
pos = trk->start + 150;
FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr);
*track_num = trk->track_number;
*attr = trk->attr;
return 1;
}
int
cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr)
{
track_t *trk = &cdi->tracks[track - 1];
if ((track < 1) || (track > cdi->tracks_num))
return 0;
*start = (uint32_t) trk->start;
*track_num = trk->track_number;
*attr = trk->attr;
@@ -335,8 +375,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
trk = &cdi->tracks[track];
track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448));
if (raw && !track_is_raw)
return 0;
seek = trk->skip + ((sect - trk->start) * trk->sector_size);
if (track_is_raw)
@@ -551,6 +590,7 @@ cdi_load_iso(cd_img_t *cdi, const wchar_t *filename)
}
trk.length = trk.file->get_length(trk.file) / trk.sector_size;
cdrom_image_backend_log("ISO: Data track: length = %" PRIu64 ", sector_size = %i\n", trk.length, trk.sector_size);
cdi_track_push_back(cdi, &trk);
/* Lead out track. */
@@ -624,12 +664,11 @@ cdi_cue_get_buffer(char *str, char **line, int up)
static int
cdi_cue_get_keyword(char **dest, char **line)
{
char temp[1024];
int success;
success = cdi_cue_get_buffer(temp, line, 1);
success = cdi_cue_get_buffer(temp_keyword, line, 1);
if (success)
*dest = temp;
*dest = temp_keyword;
return success;
}
@@ -687,6 +726,10 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u
if ((cdi->tracks != NULL) && (cdi->tracks_num != 0))
prev = &cdi->tracks[cdi->tracks_num - 1];
else if ((cdi->tracks == NULL) && (cdi->tracks_num != 0)) {
fatal("NULL cdi->tracks with non-zero cdi->tracks_num\n");
return 0;
}
/* First track (track number must be 1). */
if (cdi->tracks_num == 0) {
@@ -790,6 +833,8 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile)
success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap);
else
success = 1;
if (!success)
break;
trk.start = 0;
trk.skip = 0;
@@ -884,6 +929,8 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile)
success = cdi_add_track(cdi, &trk, &shift, prestart, &total_pregap, cur_pregap);
else
success = 1;
if (!success)
break;
can_add_track = 0;
memset(ansi, 0, MAX_FILENAME_LENGTH * sizeof(char));

View File

@@ -9,15 +9,15 @@
* CD-ROM image file handling module header , translated to C
* from cdrom_dosbox.h.
*
* Version: @(#)cdrom_image_backend.h 1.0.1 2019/12/21
* Version: @(#)cdrom_image_backend.h 1.0.2 2020/01/17
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* The DOSBox Team, <unknown>
*
* Copyright 2016-2019 Miran Grca.
* Copyright 2017-2019 Fred N. van Kempen.
* Copyright 2002-2019 The DOSBox Team.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2002-2020 The DOSBox Team.
*/
#ifndef CDROM_IMAGE_BACKEND_H
#define CDROM_IMAGE_BACKEND_H
@@ -41,7 +41,7 @@
typedef struct SMSF {
uint8_t min;
uint16_t min;
uint8_t sec;
uint8_t fr;
} TMSF;
@@ -74,7 +74,9 @@ typedef struct {
extern void cdi_close(cd_img_t *cdi);
extern int cdi_set_device(cd_img_t *cdi, const wchar_t *path);
extern int cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out);
extern int cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out);
extern int cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr);
extern int cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr);
extern int cdi_get_track(cd_img_t *cdi, uint32_t sector);
extern int cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos);
extern int cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector);

View File

@@ -20,19 +20,18 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../timer.h"
#include "../device.h"
#include "../keyboard.h"
#include "../io.h"
#include "../mem.h"
#include "../mouse.h"
#include "../port_92.h"
#include "../sio.h"
#include "../disk/hdc.h"
#include "../video/video.h"
#include "../video/vid_ht216.h"
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "device.h"
#include "keyboard.h"
#include "86box_io.h"
#include "mem.h"
#include "mouse.h"
#include "port_92.h"
#include "sio.h"
#include "hdc.h"
#include "video.h"
#include "chipset.h"

View File

@@ -20,13 +20,13 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "../io.h"
#include "../rom.h"
#include "../pci.h"
#include "../device.h"
#include "../keyboard.h"
#include "86box.h"
#include "mem.h"
#include "86box_io.h"
#include "rom.h"
#include "pci.h"
#include "device.h"
#include "keyboard.h"
#include "chipset.h"

View File

@@ -21,19 +21,19 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../timer.h"
#include "../io.h"
#include "../mem.h"
#include "../device.h"
#include "../keyboard.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../disk/hdc.h"
#include "../disk/hdc_ide.h"
#include "../timer.h"
#include "../port_92.h"
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "86box_io.h"
#include "mem.h"
#include "device.h"
#include "keyboard.h"
#include "fdd.h"
#include "fdc.h"
#include "hdc.h"
#include "hdc_ide.h"
#include "timer.h"
#include "port_92.h"
#include "chipset.h"

View File

@@ -8,11 +8,11 @@
*
* Handling of the emulated chipsets.
*
* Version: @(#)machine.h 1.0.0 2019/05/13
* Version: @(#)machine.h 1.0.2 2020/01/24
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2019 Miran Grca.
* Copyright 2019,2020 Miran Grca.
*/
#ifndef EMU_CHIPSET_H
# define EMU_CHIPSET_H
@@ -33,15 +33,19 @@ extern const device_t headland_386_device;
/* Intel 4x0xX */
extern const device_t i420tx_device;
extern const device_t i420zx_device;
extern const device_t i430lx_device;
extern const device_t i430nx_device;
extern const device_t i430fx_device;
extern const device_t i430fx_pb640_device;
extern const device_t i430hx_device;
extern const device_t i430vx_device;
extern const device_t i430tx_device;
#if defined(DEV_BRANCH) && defined(USE_I686)
extern const device_t i440fx_device;
#endif
extern const device_t i440bx_device;
extern const device_t i440zx_device;
/* NEAT */
extern const device_t neat_device;
@@ -61,6 +65,12 @@ extern const device_t sis_85c496_device;
extern const device_t sis_85c50x_device;
#endif
/* VIA */
extern const device_t via_mvp3_device;
/* VLSI */
extern const device_t vlsi_scamp_device;
/* WD */
extern const device_t wd76c10_device;

View File

@@ -25,18 +25,18 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../cpu/x86.h"
#include "../timer.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../device.h"
#include "../keyboard.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../port_92.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "timer.h"
#include "86box_io.h"
#include "mem.h"
#include "rom.h"
#include "device.h"
#include "keyboard.h"
#include "fdd.h"
#include "fdc.h"
#include "port_92.h"
#include "chipset.h"

File diff suppressed because it is too large Load Diff

View File

@@ -24,15 +24,15 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../keyboard.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "86box.h"
#include "device.h"
#include "timer.h"
#include "fdd.h"
#include "fdc.h"
#include "keyboard.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "chipset.h"
#define NEAT_DEBUG 0
@@ -565,7 +565,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
case REG_RB7:
val &= RB7_MASK;
*reg = (*reg & ~RB7_MASK) | val;
*reg = val;
#if NEAT_DEBUG > 1
neat_log("NEAT: RB7=%02x(%02x)\n", val, *reg);
#endif

View File

@@ -258,15 +258,15 @@ SeeAlso: #P0178,#P0187
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../timer.h"
#include "../io.h"
#include "../device.h"
#include "../keyboard.h"
#include "../mem.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "86box_io.h"
#include "device.h"
#include "keyboard.h"
#include "mem.h"
#include "fdd.h"
#include "fdc.h"
#include "chipset.h"

775
src/chipset/scamp.c Normal file
View File

@@ -0,0 +1,775 @@
/*
* 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 VLSI 82C311 ("SCAMP") chipset.
*
* Note: The datasheet mentions that the chipset supports up to 8MB
* of DRAM. This is intepreted as 'being able to refresh up to
* 8MB of DRAM chips', because it works fine with bus-based
* memory expansion.
*
* Version: @(#)scamp.c 1.0.1 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
*
* Copyright 2020 Sarah Walker.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "device.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "port_92.h"
#include "chipset.h"
typedef struct {
void *parent;
int bank;
} ram_struct_t;
typedef struct {
int cfg_index;
uint8_t cfg_regs[256];
int cfg_enable;
int ram_config;
mem_mapping_t ram_mapping[2];
ram_struct_t ram_struct[3];
uint32_t ram_virt_base[2], ram_phys_base[2];
uint32_t ram_mask[2];
int row_virt_shift[2], row_phys_shift[2];
int ram_interleaved[2];
int ibank_shift[2];
} scamp_t;
#define CFG_ID 0x00
#define CFG_SLTPTR 0x02
#define CFG_RAMMAP 0x03
#define CFG_EMSEN1 0x0b
#define CFG_EMSEN2 0x0c
#define CFG_ABAXS 0x0e
#define CFG_CAXS 0x0f
#define CFG_DAXS 0x10
#define CFG_FEAXS 0x11
#define ID_VL82C311 0xd6
#define RAMMAP_REMP386 (1 << 4)
/*Commodore SL386SX requires proper memory slot decoding to detect memory size.
Therefore we emulate the SCAMP memory address decoding, and therefore are
limited to the DRAM combinations supported by the actual chip*/
enum
{
BANK_NONE,
BANK_256K,
BANK_256K_INTERLEAVED,
BANK_1M,
BANK_1M_INTERLEAVED,
BANK_4M,
BANK_4M_INTERLEAVED
};
static const struct
{
int size_kb;
int rammap;
int bank[2];
} ram_configs[] =
{
{512, 0x0, {BANK_256K, BANK_NONE}},
{1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}},
{1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}},
{2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}},
{3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}},
{4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}},
{5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}},
{6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}},
{8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}},
{12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}},
{16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}},
};
static const struct
{
int bank[2];
int remapped;
} rammap[16] =
{
{{BANK_256K, BANK_NONE}, 0},
{{BANK_256K_INTERLEAVED, BANK_NONE}, 0},
{{BANK_256K_INTERLEAVED, BANK_256K}, 0},
{{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0},
{{BANK_1M, BANK_NONE}, 0},
{{BANK_1M_INTERLEAVED, BANK_NONE}, 0},
{{BANK_1M_INTERLEAVED, BANK_1M}, 0},
{{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
{{BANK_4M, BANK_NONE}, 0},
{{BANK_4M_INTERLEAVED, BANK_NONE}, 0},
{{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/
{{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/
{{BANK_256K_INTERLEAVED, BANK_1M}, 0},
{{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
{{BANK_1M_INTERLEAVED, BANK_4M}, 0},
{{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/
};
/*The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous,
so we use separate routines for that special case*/
static uint8_t
ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return 0xff;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
ram[addr + dev->ram_phys_base[bank]] = val;
}
/*Read/write handlers for interleaved memory banks. We must keep CPU and ram array
mapping linear, otherwise we won't be able to execute code from interleaved banks*/
static uint8_t
ram_mirrored_interleaved_read(uint32_t addr, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return 0xff;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
}
else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
ram[addr + dev->ram_phys_base[bank]] = val;
}
static uint8_t
ram_mirrored_read(uint32_t addr, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_write(uint32_t addr, uint8_t val, void *priv)
{
ram_struct_t *rs = (ram_struct_t *) priv;
scamp_t *dev = rs->parent;
int bank = rs->bank;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
ram[addr + dev->ram_phys_base[bank]] = val;
}
static void
recalc_mappings(void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int c;
uint32_t virt_base = 0;
uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf;
int bank_nr = 0;
for (c = 0; c < 2; c++)
mem_mapping_disable(&dev->ram_mapping[c]);
/*Once the BIOS programs the correct DRAM configuration, switch to regular
linear memory mapping*/
if (cur_rammap == ram_configs[dev->ram_config].rammap) {
mem_mapping_set_handler(&ram_low_mapping,
mem_read_ram, mem_read_ramw, mem_read_raml,
mem_write_ram, mem_write_ramw, mem_write_raml);
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_enable(&ram_high_mapping);
return;
} else {
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
mem_mapping_disable(&ram_low_mapping);
}
if (rammap[cur_rammap].bank[0] == BANK_NONE)
bank_nr = 1;
/* pclog("Bank remap, cur_rammap=%x\n", cur_rammap); */
for (; bank_nr < 2; bank_nr++) {
uint32_t old_virt_base = virt_base;
int phys_bank = ram_configs[dev->ram_config].bank[bank_nr];
/* pclog(" Bank %i: phys_bank=%i rammap_bank=%i virt_base=%08x phys_base=%08x\n", bank_nr, phys_bank, rammap[cur_rammap].bank[bank_nr], virt_base, dev->ram_phys_base[bank_nr]); */
dev->ram_virt_base[bank_nr] = virt_base;
if (virt_base == 0) {
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_NONE:
fatal("Bank 0 is empty!\n");
break;
case BANK_256K:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
}
virt_base += 512*1024;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_256K_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
}
virt_base += 512*1024*2;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_1M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 2048*1024;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_1M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 2048*1024*2;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_4M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 8192*1024;
dev->row_virt_shift[bank_nr] = 12;
break;
case BANK_4M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 8192*1024*2;
dev->row_virt_shift[bank_nr] = 12;
break;
}
} else {
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_NONE:
break;
case BANK_256K:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 512*1024;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_256K_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 512*1024*2;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_1M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 2048*1024;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_1M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 2048*1024*2;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_4M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 8192*1024;
dev->row_virt_shift[bank_nr] = 12;
break;
case BANK_4M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 8192*1024*2;
dev->row_virt_shift[bank_nr] = 12;
break;
}
}
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_256K: case BANK_1M: case BANK_4M:
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
/*pclog(" not interleaved\n");*/
break;
case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED:
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
/*pclog(" interleaved\n");*/
break;
case BANK_4M_INTERLEAVED:
if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) {
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_256k_in_4mi_read, NULL, NULL,
ram_mirrored_256k_in_4mi_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_256k_in_4mi_read, NULL, NULL,
ram_mirrored_256k_in_4mi_write, NULL, NULL);
/*pclog(" 256k in 4mi\n");*/
} else {
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
/*pclog(" interleaved\n");*/
}
break;
}
}
}
#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
static void
shadow_control(uint32_t addr, uint32_t size, int state)
{
/* pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); */
switch (state) {
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
scamp_write(uint16_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
/* pclog("scamp_write: addr=%04x val=%02x\n", addr, val); */
switch (addr) {
case 0xec:
if (dev->cfg_enable)
dev->cfg_index = val;
break;
case 0xed:
if (dev->cfg_enable) {
if (dev->cfg_index >= 0x02 && dev->cfg_index <= 0x16) {
dev->cfg_regs[dev->cfg_index] = val;
/* pclog("SCAMP CFG[%02x]=%02x\n", dev->cfg_index, val); */
switch (dev->cfg_index) {
case CFG_SLTPTR:
break;
case CFG_RAMMAP:
recalc_mappings(dev);
mem_mapping_disable(&ram_remapped_mapping);
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) {
/*Enabling remapping will disable all shadowing*/
mem_remap_top(384);
shadow_control(0xa0000, 0x60000, 0);
} else {
shadow_control(0xa0000, 0x8000, dev->cfg_regs[CFG_ABAXS] & 3);
shadow_control(0xa8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 2) & 3);
shadow_control(0xb0000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 4) & 3);
shadow_control(0xb8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 6) & 3);
shadow_control(0xc0000, 0x4000, dev->cfg_regs[CFG_CAXS] & 3);
shadow_control(0xc4000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 2) & 3);
shadow_control(0xc8000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 4) & 3);
shadow_control(0xcc000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 6) & 3);
shadow_control(0xd0000, 0x4000, dev->cfg_regs[CFG_DAXS] & 3);
shadow_control(0xd4000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 2) & 3);
shadow_control(0xd8000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 4) & 3);
shadow_control(0xdc000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 6) & 3);
shadow_control(0xe0000, 0x8000, dev->cfg_regs[CFG_FEAXS] & 3);
shadow_control(0xe8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 2) & 3);
shadow_control(0xf0000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 4) & 3);
shadow_control(0xf8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 6) & 3);
}
break;
case CFG_ABAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xa0000, 0x8000, val & 3);
shadow_control(0xa8000, 0x8000, (val >> 2) & 3);
shadow_control(0xb0000, 0x8000, (val >> 4) & 3);
shadow_control(0xb8000, 0x8000, (val >> 6) & 3);
}
break;
case CFG_CAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xc0000, 0x4000, val & 3);
shadow_control(0xc4000, 0x4000, (val >> 2) & 3);
shadow_control(0xc8000, 0x4000, (val >> 4) & 3);
shadow_control(0xcc000, 0x4000, (val >> 6) & 3);
}
break;
case CFG_DAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xd0000, 0x4000, val & 3);
shadow_control(0xd4000, 0x4000, (val >> 2) & 3);
shadow_control(0xd8000, 0x4000, (val >> 4) & 3);
shadow_control(0xdc000, 0x4000, (val >> 6) & 3);
}
break;
case CFG_FEAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xe0000, 0x8000, val & 3);
shadow_control(0xe8000, 0x8000, (val >> 2) & 3);
shadow_control(0xf0000, 0x8000, (val >> 4) & 3);
shadow_control(0xf8000, 0x8000, (val >> 6) & 3);
}
break;
}
}
}
break;
case 0xee:
if (dev->cfg_enable && mem_a20_alt)
outb(0x92, inb(0x92) & ~2);
break;
}
}
static uint8_t
scamp_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
switch (addr) {
case 0xee:
if (!mem_a20_alt)
outb(0x92, inb(0x92) | 2);
break;
case 0xef:
softresetx86();
cpu_set_edx();
break;
}
/* pclog("scamp_read: addr=%04x ret=%02x\n", addr, ret); */
return ret;
}
static void
scamp_close(void *priv)
{
scamp_t *dev = (scamp_t *) priv;
free(dev);
}
static void *
scamp_init(const device_t *info)
{
uint32_t addr;
int c;
scamp_t *dev = (scamp_t *)malloc(sizeof(scamp_t));
memset(dev, 0, sizeof(scamp_t));
dev->cfg_regs[CFG_ID] = ID_VL82C311;
dev->cfg_enable = 1;
io_sethandler(0x00e8, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00ea, 0x0006,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00f4, 0x0002,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00f9, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00fb, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
dev->ram_config = 0;
/*Find best fit configuration for the requested memory size*/
for (c = 0; c < NR_ELEMS(ram_configs); c++) {
if (mem_size < ram_configs[c].size_kb)
break;
dev->ram_config = c;
}
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
dev->ram_struct[2].parent = dev;
dev->ram_struct[2].bank = 0;
mem_mapping_set_p(&ram_low_mapping, (void *) &dev->ram_struct[2]);
mem_mapping_disable(&ram_high_mapping);
addr = 0;
for (c = 0; c < 2; c++) {
dev->ram_struct[c].parent = dev;
dev->ram_struct[c].bank = c;
mem_mapping_add(&dev->ram_mapping[c], 0, 0,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL,
&ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]);
mem_mapping_disable(&dev->ram_mapping[c]);
dev->ram_phys_base[c] = addr;
/* pclog("Bank calc : %i = %08x\n", c ,addr);*/
switch (ram_configs[dev->ram_config].bank[c]) {
case BANK_NONE:
dev->ram_mask[c] = 0;
dev->ram_interleaved[c] = 0;
break;
case BANK_256K:
addr += 512*1024;
dev->ram_mask[c] = 0x1ff;
dev->row_phys_shift[c] = 10;
dev->ram_interleaved[c] = 0;
break;
case BANK_256K_INTERLEAVED:
addr += 512*1024*2;
dev->ram_mask[c] = 0x1ff;
dev->row_phys_shift[c] = 10;
dev->ibank_shift[c] = 19;
dev->ram_interleaved[c] = 1;
break;
case BANK_1M:
addr += 2048*1024;
dev->ram_mask[c] = 0x3ff;
dev->row_phys_shift[c] = 11;
dev->ram_interleaved[c] = 0;
break;
case BANK_1M_INTERLEAVED:
addr += 2048*1024*2;
dev->ram_mask[c] = 0x3ff;
dev->row_phys_shift[c] = 11;
dev->ibank_shift[c] = 21;
dev->ram_interleaved[c] = 1;
break;
case BANK_4M:
addr += 8192*1024;
dev->ram_mask[c] = 0x7ff;
dev->row_phys_shift[c] = 12;
dev->ram_interleaved[c] = 0;
break;
case BANK_4M_INTERLEAVED:
addr += 8192*1024*2;
dev->ram_mask[c] = 0x7ff;
dev->row_phys_shift[c] = 12;
dev->ibank_shift[c] = 23;
dev->ram_interleaved[c] = 1;
break;
}
}
mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
return dev;
}
const device_t vlsi_scamp_device = {
"VLSI SCAMP",
0,
0,
scamp_init, scamp_close, NULL,
NULL, NULL, NULL,
NULL
};

View File

@@ -23,24 +23,19 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#ifdef USE_NEW_DYNAREC
#include "../cpu_new/cpu.h"
#include "../cpu_new/x86.h"
#else
#include "../cpu/cpu.h"
#include "../cpu/x86.h"
#endif
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../keyboard.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../port_92.h"
#include "../rom.h"
#include "86box.h"
#include "device.h"
#include "cpu.h"
#include "x86.h"
#include "timer.h"
#include "fdd.h"
#include "fdc.h"
#include "keyboard.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "port_92.h"
#include "rom.h"
#include "chipset.h"
@@ -1056,17 +1051,14 @@ scat_out(uint16_t port, uint8_t val, void *priv)
break;
case SCAT_EMS_CONTROL:
io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
if (val & 0x40) {
if (val & 1) {
if (val & 1)
io_sethandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
io_removehandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
} else {
else
io_sethandler(0x0208, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
io_removehandler(0x0218, 3, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
}
} else {
io_removehandler(0x0208, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
io_removehandler(0x0218, 0x0003, scat_in, NULL, NULL, scat_out, NULL, NULL, dev);
}
set_global_EMS_state(dev, val & 0x80);
reg_valid = 1;
@@ -1338,13 +1330,24 @@ static void
mem_write_scatb(uint32_t addr, uint8_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
scat_t *dev = (scat_t *)page->scat;
scat_t *dev;
uint32_t oldaddr = addr, chkaddr;
addr = get_addr(dev, addr, page);
chkaddr = page ? addr : oldaddr;
if (page == NULL)
dev = NULL;
else
dev = (scat_t *)page->scat;
if (dev == NULL)
chkaddr = oldaddr;
else {
addr = get_addr(dev, addr, page);
chkaddr = addr;
}
if (chkaddr >= 0xc0000 && chkaddr < 0x100000) {
if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return;
if ((dev == NULL) || (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))))
return;
}
if (addr < ((uint32_t)mem_size << 10))
@@ -1356,13 +1359,24 @@ static void
mem_write_scatw(uint32_t addr, uint16_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
scat_t *dev = (scat_t *)page->scat;
scat_t *dev;
uint32_t oldaddr = addr, chkaddr;
addr = get_addr(dev, addr, page);
chkaddr = page ? addr : oldaddr;
if (page == NULL)
dev = NULL;
else
dev = (scat_t *)page->scat;
if (dev == NULL)
chkaddr = oldaddr;
else {
addr = get_addr(dev, addr, page);
chkaddr = addr;
}
if (chkaddr >= 0xc0000 && chkaddr < 0x100000) {
if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return;
if (dev != NULL && (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))))
return;
}
if (addr < ((uint32_t)mem_size << 10))
@@ -1374,14 +1388,26 @@ static void
mem_write_scatl(uint32_t addr, uint32_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
scat_t *dev = (scat_t *)page->scat;
scat_t *dev;
uint32_t oldaddr = addr, chkaddr;
addr = get_addr(dev, addr, page);
chkaddr = page ? addr : oldaddr;
if (chkaddr >= 0xc0000 && chkaddr < 0x100000) {
if (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))) return;
if (page == NULL)
dev = NULL;
else
dev = (scat_t *)page->scat;
if (dev == NULL)
chkaddr = oldaddr;
else {
addr = get_addr(dev, addr, page);
chkaddr = addr;
}
if (chkaddr >= 0xc0000 && chkaddr < 0x100000) {
if (dev != NULL && (dev->regs[SCAT_RAM_WRITE_PROTECT] & (1 << ((chkaddr - 0xc0000) >> 15))))
return;
}
if (addr < ((uint32_t)mem_size << 10))
*(uint32_t *)&ram[addr] = val;
}

View File

@@ -22,20 +22,20 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../mem.h"
#include "../io.h"
#include "../lpt.h"
#include "../rom.h"
#include "../pci.h"
#include "../device.h"
#include "../disk/hdc_ide.h"
#include "../keyboard.h"
#include "../timer.h"
#include "../port_92.h"
#include "../serial.h"
#include "../machine/machine.h"
#include "86box.h"
#include "cpu.h"
#include "mem.h"
#include "86box_io.h"
#include "lpt.h"
#include "rom.h"
#include "pci.h"
#include "device.h"
#include "hdc_ide.h"
#include "keyboard.h"
#include "timer.h"
#include "port_92.h"
#include "serial.h"
#include "machine.h"
#include "chipset.h"

View File

@@ -21,18 +21,18 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../mem.h"
#include "../io.h"
#include "../rom.h"
#include "../pci.h"
#include "../device.h"
#include "../keyboard.h"
#include "../timer.h"
#include "../port_92.h"
#include "../disk/hdc_ide.h"
#include "../machine/machine.h"
#include "86box.h"
#include "cpu.h"
#include "mem.h"
#include "86box_io.h"
#include "rom.h"
#include "pci.h"
#include "device.h"
#include "keyboard.h"
#include "timer.h"
#include "port_92.h"
#include "hdc_ide.h"
#include "machine.h"
#include "chipset.h"
@@ -142,7 +142,6 @@ sis_85c496_write(int func, int addr, uint8_t val, void *priv)
port_92_remove(dev->port_92);
if (val & 0x02)
port_92_add(dev->port_92);
pclog("Port 92: %sabled\n", (val & 0x02) ? "En" : "Dis");
}
break;
@@ -197,10 +196,8 @@ sis_85c496_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x67:
if (valxor & 0x60) {
if (valxor & 0x60)
port_92_set_features(dev->port_92, !!(val & 0x20), !!(val & 0x40));
pclog("[Port 92] Set features: %sreset, %sA20\n", !!(val & 0x20) ? "" : "no ", !!(val & 0x40) ? "" : "no ");
}
break;
case 0x82:
@@ -239,15 +236,18 @@ static uint8_t
sis_85c496_read(int func, int addr, void *priv)
{
sis_85c496_t *dev = (sis_85c496_t *) priv;
uint8_t ret = dev->pci_conf[addr];
switch (addr) {
case 0x82: /*Port 22h Mirror*/
return inb(0x22);
ret = inb(0x22);
break;
case 0x70: /*Port 70h Mirror*/
return inb(0x70);
ret = inb(0x70);
break;
}
return dev->pci_conf[addr];
return ret;
}
@@ -313,7 +313,7 @@ static void
dev->pci_conf[0xd0] = 0x78; /* ROM at E0000-FFFFF, Flash enable. */
dev->pci_conf[0xd1] = 0xff;
pci_add_card(5, sis_85c496_read, sis_85c496_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c496_read, sis_85c496_write, dev);
sis_85c497_reset(dev);

View File

@@ -20,14 +20,14 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "../io.h"
#include "../rom.h"
#include "../pci.h"
#include "../device.h"
#include "../keyboard.h"
#include "../port_92.h"
#include "86box.h"
#include "mem.h"
#include "86box_io.h"
#include "rom.h"
#include "pci.h"
#include "device.h"
#include "keyboard.h"
#include "port_92.h"
#include "chipset.h"

324
src/chipset/via_mvp3.c Normal file
View File

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

View File

@@ -23,17 +23,17 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../timer.h"
#include "../io.h"
#include "../keyboard.h"
#include "../mem.h"
#include "../port_92.h"
#include "../serial.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../video/vid_paradise.h"
#include "86box.h"
#include "device.h"
#include "timer.h"
#include "86box_io.h"
#include "keyboard.h"
#include "mem.h"
#include "port_92.h"
#include "serial.h"
#include "fdd.h"
#include "fdc.h"
#include "video.h"
#include "chipset.h"

View File

@@ -34,7 +34,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "cpu/cpu.h"
#include "cpu.h"
#include "device.h"
#include "timer.h"
#include "nvr.h"
@@ -42,24 +42,23 @@
#include "isamem.h"
#include "isartc.h"
#include "lpt.h"
#include "disk/hdd.h"
#include "disk/hdc.h"
#include "disk/hdc_ide.h"
#include "floppy/fdd.h"
#include "floppy/fdc.h"
#include "game/gameport.h"
#include "machine/machine.h"
#include "hdd.h"
#include "hdc.h"
#include "hdc_ide.h"
#include "fdd.h"
#include "fdc.h"
#include "gameport.h"
#include "machine.h"
#include "mouse.h"
#include "network/network.h"
#include "scsi/scsi.h"
#include "scsi/scsi_device.h"
#include "cdrom/cdrom.h"
#include "disk/zip.h"
#include "sound/sound.h"
#include "sound/midi.h"
#include "sound/snd_mpu401.h"
#include "sound/sound.h"
#include "video/video.h"
#include "network.h"
#include "scsi.h"
#include "scsi_device.h"
#include "cdrom.h"
#include "zip.h"
#include "sound.h"
#include "midi.h"
#include "snd_mpu401.h"
#include "video.h"
#include "plat.h"
#include "plat_midi.h"
#include "ui.h"
@@ -81,7 +80,7 @@ typedef struct {
list_t list;
char name[128];
char data[256];
char data[512];
wchar_t wdata[512];
} entry_t;
@@ -309,7 +308,7 @@ config_read(wchar_t *fn)
/* Create a new section and insert it. */
ns = malloc(sizeof(section_t));
memset(ns, 0x00, sizeof(section_t));
strncpy(ns->name, sname, sizeof(ns->name));
memcpy(ns->name, sname, 128);
list_add(&ns->list, &config_head);
/* New section is now the current one. */
@@ -339,7 +338,7 @@ config_read(wchar_t *fn)
/* Allocate a new variable entry.. */
ne = malloc(sizeof(entry_t));
memset(ne, 0x00, sizeof(entry_t));
strncpy(ne->name, ename, sizeof(ne->name));
memcpy(ne->name, ename, 128);
wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1);
ne->wdata[sizeof_w(ne->wdata)-1] = L'\0';
wcstombs(ne->data, ne->wdata, sizeof(ne->data));
@@ -395,7 +394,7 @@ config_write(wchar_t *fn)
ent = (entry_t *)sec->entry_head.next;
while (ent != NULL) {
if (ent->name[0] != '\0') {
mbstowcs(wtemp, ent->name, sizeof_w(wtemp));
mbstowcs(wtemp, ent->name, 128);
if (ent->wdata[0] == L'\0')
fwprintf(f, L"%ls = \n", wtemp);
else
@@ -566,6 +565,7 @@ load_video(void)
{
char *cat = "Video";
char *p;
int free_p = 0;
if (machines[machine].flags & MACHINE_VIDEO_FIXED) {
config_delete_var(cat, "gfxcard");
@@ -580,8 +580,11 @@ load_video(void)
p = (char *)malloc((strlen("none")+1)*sizeof(char));
strcpy(p, "none");
}
free_p = 1;
}
gfxcard = video_get_video_from_internal_name(p);
if (free_p)
free(p);
}
voodoo_enabled = !!config_get_int(cat, "voodoo", 0);
@@ -603,7 +606,7 @@ load_input_devices(void)
else
mouse_type = 0;
joystick_type = config_get_int(cat, "joystick_type", 7);
joystick_type = config_get_int(cat, "joystick_type", JOYSTICK_TYPE_NONE);
for (c=0; c<joystick_get_max_joysticks(joystick_type); c++) {
sprintf(temp, "joystick_%i_nr", c);
@@ -663,7 +666,10 @@ load_sound(void)
memset(temp, '\0', sizeof(temp));
p = config_get_string(cat, "sound_type", "float");
strcpy(temp, p);
if (strlen(p) <= 511)
strcpy(temp, p);
else
strncpy(temp, p, 511);
if (!strcmp(temp, "float") || !strcmp(temp, "1"))
sound_is_float = 1;
else
@@ -707,7 +713,10 @@ load_network(void)
strcpy(network_host, "none");
} else {
strcpy(network_host, p);
if (strlen(p) <= 522)
strcpy(network_host, p);
else
strncpy(network_host, p, 522);
}
} else
strcpy(network_host, "none");
@@ -760,7 +769,7 @@ load_other_peripherals(void)
char *cat = "Other peripherals";
char *p;
char temp[512];
int c;
int c, free_p = 0;
p = config_get_string(cat, "scsicard", NULL);
if (p != NULL)
@@ -777,6 +786,7 @@ load_other_peripherals(void)
p = (char *)malloc((strlen("none")+1)*sizeof(char));
strcpy(p, "none");
}
free_p = 1;
}
if (!strcmp(p, "mfm_xt"))
hdc_current = hdc_get_from_internal_name("st506_xt");
@@ -787,10 +797,16 @@ load_other_peripherals(void)
else
hdc_current = hdc_get_from_internal_name(p);
if (free_p) {
free(p);
p = NULL;
}
ide_ter_enabled = !!config_get_int(cat, "ide_ter", 0);
ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0);
bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0);
postcard_enabled = !!config_get_int(cat, "postcard_enabled", 0);
for (c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
@@ -1250,7 +1266,7 @@ config_load(void)
gfxcard = video_get_video_from_internal_name("cga");
vid_api = plat_vidapi("default");
time_sync = TIME_SYNC_ENABLED;
joystick_type = 7;
joystick_type = JOYSTICK_TYPE_NONE;
hdc_current = hdc_get_from_internal_name("none");
serial_enabled[0] = 1;
serial_enabled[1] = 1;
@@ -1472,7 +1488,7 @@ save_input_devices(void)
config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type));
if (joystick_type == 7) {
if (joystick_type == JOYSTICK_TYPE_NONE) {
config_delete_var(cat, "joystick_type");
for (c = 0; c < 16; c++) {
@@ -1671,6 +1687,11 @@ save_other_peripherals(void)
else
config_set_int(cat, "bugger_enabled", bugger_enabled);
if (postcard_enabled == 0)
config_delete_var(cat, "postcard_enabled");
else
config_set_int(cat, "postcard_enabled", postcard_enabled);
for (c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
if (isamem_type[c] == 0)
@@ -1695,7 +1716,7 @@ static void
save_hard_disks(void)
{
char *cat = "Hard disks";
char temp[32], tmp2[64];
char temp[32], tmp2[512];
char *p;
int c;
@@ -2096,7 +2117,7 @@ config_set_int(char *head, char *name, int val)
ent = create_entry(section, name);
sprintf(ent->data, "%i", val);
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
mbstowcs(ent->wdata, ent->data, 512);
}
@@ -2154,7 +2175,7 @@ config_set_mac(char *head, char *name, int val)
sprintf(ent->data, "%02x:%02x:%02x",
(val>>16)&0xff, (val>>8)&0xff, val&0xff);
mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata));
mbstowcs(ent->wdata, ent->data, 512);
}

View File

@@ -1,256 +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.h"
#include "cpu.h"
#include "../timer.h"
#include "x86.h"
#include "x87.h"
#include "../nmi.h"
#include "../mem.h"
#include "../pic.h"
#include "../pit.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "386_common.h"
#define CPU_BLOCK_END()
extern int codegen_flags_changed;
int cpl_override = 0, fpucount = 0;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int stack32, timetolive;
uint16_t oldcs;
uint32_t use32;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t *eal_r, *eal_w;
uint32_t oxpc, cr2, cr3, cr4;
uint32_t dr[8];
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg gdt,ldt,idt,tr;
x86seg _oldds;
uint32_t rmdat;
#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 0; }
#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 0
#include "x86_flags.h"
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
extern int xout;
int oldi;
uint32_t testr[9];
extern int dontprint;
#undef NOTRM
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
{ \
x86_int(6); \
return 0; \
}
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "x86_ops.h"
#undef NOTRM
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
{ \
x86_int(6); \
break; \
}
#ifdef ENABLE_386_LOG
int x386_do_log = ENABLE_386_LOG;
static void
x386_log(const char *fmt, ...)
{
va_list ap;
if (x386_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_log(fmt, ...)
#endif
void exec386(int cycs)
{
int vector, tempi, cycdiff, oldcyc;
int ins_cycles;
uint32_t addr;
cycles+=cycs;
while (cycles>0)
{
int cycle_period = (timer_target - (uint32_t)tsc) + 1;
x86_was_reset = 0;
cycdiff=0;
oldcyc=cycles;
while (cycdiff < cycle_period)
{
ins_cycles = cycles;
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl=CPL;
cpu_state.op32 = use32;
x86_was_reset = 0;
dontprint=0;
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(x86_was_reset)
break;
}
if (!use32) cpu_state.pc &= 0xffff;
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;
x386_log("Double fault %i\n", ins);
pmodeint(8, 0);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
x386_log("Triple fault - reset\n");
}
}
}
ins_cycles -= cycles;
tsc += ins_cycles;
cycdiff=oldcyc-cycles;
if (trap)
{
flags_rebuild();
/* oldpc=pc; */
/* oldcs=CS; */
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)
{
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)
{
flags_rebuild();
if (msw&1)
{
pmodeint(vector,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (vector << 2) + idt.base;
cpu_state.flags&=~I_FLAG;
cpu_state.flags&=~T_FLAG;
oxpc = cpu_state.pc;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
}
ins++;
if (timetolive)
{
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,9 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "86box.h"
#include "mem.h"
#include "cpu.h"
#include "x86_ops.h"
#include "codegen.h"

View File

@@ -38,7 +38,7 @@
#define _CODEGEN_H_
#include "../mem.h"
#include "x86_ops.h"
#include "../cpu_common/x86_ops.h"
#ifdef __amd64__
#include "codegen_x86-64.h"
@@ -315,9 +315,6 @@ extern int cpu_recomp_evicted, cpu_recomp_evicted_latched;
extern int cpu_recomp_reuse, cpu_recomp_reuse_latched;
extern int cpu_recomp_removed, cpu_recomp_removed_latched;
extern int cpu_reps, cpu_reps_latched;
extern int cpu_notreps, cpu_notreps_latched;
extern int codegen_block_cycles;
extern void (*codegen_timing_start)();

View File

@@ -2,8 +2,9 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "86box.h"
#include "mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"

View File

@@ -4663,11 +4663,6 @@ static inline void FP_OP_IL(int op)
FP_OP_MEM(op);
}
#define C0 (1<<8)
#define C1 (1<<9)
#define C2 (1<<10)
#define C3 (1<<14)
static inline void FP_COMPARE_REG(int dst, int src)
{
addbyte(0x8b); /*MOV EAX, [TOP]*/

View File

@@ -2951,10 +2951,6 @@ static inline void FP_OP_IQ(int op)
}
}
#endif
#define C0 (1<<8)
#define C1 (1<<9)
#define C2 (1<<10)
#define C3 (1<<14)
static inline void FP_COMPARE_S()
{

View File

@@ -2,8 +2,8 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "86box.h"
#include "mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"

View File

@@ -12,8 +12,8 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "86box.h"
#include "mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"

View File

@@ -2,7 +2,7 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "codegen_timing_common.h"

View File

@@ -13,8 +13,8 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "86box.h"
#include "mem.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"

View File

@@ -2,7 +2,7 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"

View File

@@ -5,13 +5,13 @@
#include <stdint.h>
#include <stdlib.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "x87.h"
#include "../mem.h"
#include "mem.h"
#include "386_common.h"

View File

@@ -43,12 +43,12 @@
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../mem.h"
#include "mem.h"
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "../cpu_common/x86_ops.h"
#include "x87.h"
#include "386_common.h"

File diff suppressed because it is too large Load Diff

View File

@@ -1,569 +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
*
* Version: @(#)cpu_table.c 1.0.7 2019/10/21
*
* 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.h"
#include "cpu.h"
#include "../machine/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, 2, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/12", CPU_8086, 12000000, 3, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/16", CPU_8086, 16000000, 4, 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*/
{"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, 0, 4,4,3,3, 3},
{"RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0, 0x0430, 0, 0, 0, 6,6,3,3, 4},
{"RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0, 0x0430, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_Am386SX[] = {
/*Am386*/
{"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[] = {
/*Am386*/
{"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_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_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_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},
{"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}
};
#ifdef DEV_BRANCH
#ifdef 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
#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},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
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},
{"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}
};
#ifdef DEV_BRANCH
#ifdef 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},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
#endif
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
CPU cpus_PentiumPro[] = {
/*Intel Pentium Pro*/
{"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
/*Intel Pentium II OverDrive*/
{"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
{"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33},
{"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
{"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
{"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#endif

View File

@@ -1,75 +0,0 @@
#ifdef USE_NEW_DYNAREC
#include "../cpu_new/x86.h"
#else
extern uint8_t opcode, opcode2;
extern uint8_t flags_p;
extern uint8_t znptable8[256];
extern uint16_t zero, oldcs;
extern uint16_t lastcs, lastpc;
extern uint16_t *mod1add[2][8];
extern uint16_t znptable16[65536];
extern int x86_was_reset, trap;
extern int codegen_flat_ss, codegen_flat_ds;
extern int timetolive, keyboardtimer, trap;
extern int optype, stack32;
extern int oldcpl, cgate32, cpl_override, fpucount;
extern int nmi_enable;
extern int oddeven, inttype;
extern uint32_t use32;
extern uint32_t rmdat, easeg;
extern uint32_t oxpc, flags_zn;
extern uint32_t abrt_error;
extern uint32_t backupregs[16];
extern uint32_t *mod1seg[8];
extern uint32_t *eal_r, *eal_w;
#define fetchdat rmdat
#define setznp168 setznp16
#define getr8(r) ((r&4)?cpu_state.regs[r&3].b.h:cpu_state.regs[r&3].b.l)
#define getr16(r) cpu_state.regs[r].w
#define getr32(r) cpu_state.regs[r].l
#define setr8(r,v) if (r&4) cpu_state.regs[r&3].b.h=v; \
else cpu_state.regs[r&3].b.l=v;
#define setr16(r,v) cpu_state.regs[r].w=v
#define setr32(r,v) cpu_state.regs[r].l=v
#define fetchea() { \
rmdat = readmemb(cs + pc); \
pc++; \
reg = (rmdat >> 3) & 7; \
mod = (rmdat >> 6) & 3; \
rm = rmdat & 7; \
if (mod!=3) \
fetcheal(); \
}
#define JMP 1
#define CALL 2
#define IRET 3
#define OPTYPE_INT 4
enum
{
ABRT_NONE = 0,
ABRT_GEN,
ABRT_TS = 0xA,
ABRT_NP = 0xB,
ABRT_SS = 0xC,
ABRT_GPF = 0xD,
ABRT_PF = 0xE
};
extern void x86_doabrt(int x86_abrt);
extern void x86illegal();
extern void x86seg_reset();
extern void x86gpf(char *s, uint16_t error);
#endif

View File

@@ -1,237 +0,0 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Miscellaneous x86 CPU Instructions.
*
* Version: @(#)x86_ops.h 1.0.2 2018/05/05
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2018 Fred N. van Kempen.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef _X86_OPS_H
#define _X86_OPS_H
#define UN_USED(x) (void)(x)
typedef int (*OpFn)(uint32_t fetchdat);
#ifdef USE_DYNAREC
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f,
const OpFn *dynarec_opcodes,
const OpFn *dynarec_opcodes_0f);
extern const OpFn *x86_dynarec_opcodes;
extern const OpFn *x86_dynarec_opcodes_0f;
extern const OpFn *x86_dynarec_opcodes_d8_a16;
extern const OpFn *x86_dynarec_opcodes_d8_a32;
extern const OpFn *x86_dynarec_opcodes_d9_a16;
extern const OpFn *x86_dynarec_opcodes_d9_a32;
extern const OpFn *x86_dynarec_opcodes_da_a16;
extern const OpFn *x86_dynarec_opcodes_da_a32;
extern const OpFn *x86_dynarec_opcodes_db_a16;
extern const OpFn *x86_dynarec_opcodes_db_a32;
extern const OpFn *x86_dynarec_opcodes_dc_a16;
extern const OpFn *x86_dynarec_opcodes_dc_a32;
extern const OpFn *x86_dynarec_opcodes_dd_a16;
extern const OpFn *x86_dynarec_opcodes_dd_a32;
extern const OpFn *x86_dynarec_opcodes_de_a16;
extern const OpFn *x86_dynarec_opcodes_de_a32;
extern const OpFn *x86_dynarec_opcodes_df_a16;
extern const OpFn *x86_dynarec_opcodes_df_a32;
extern const OpFn *x86_dynarec_opcodes_REPE;
extern const OpFn *x86_dynarec_opcodes_REPNE;
extern const OpFn dynarec_ops_286[1024];
extern const OpFn dynarec_ops_286_0f[1024];
extern const OpFn dynarec_ops_386[1024];
extern const OpFn dynarec_ops_386_0f[1024];
extern const OpFn dynarec_ops_486_0f[1024];
extern const OpFn dynarec_ops_winchip_0f[1024];
extern const OpFn dynarec_ops_pentium_0f[1024];
extern const OpFn dynarec_ops_pentiummmx_0f[1024];
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
extern const OpFn dynarec_ops_c6x86mx_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_AMD_K)
extern const OpFn dynarec_ops_k6_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_I686)
extern const OpFn dynarec_ops_pentiumpro_0f[1024];
extern const OpFn dynarec_ops_pentium2d_0f[1024];
#endif
extern const OpFn dynarec_ops_fpu_287_d9_a16[256];
extern const OpFn dynarec_ops_fpu_287_d9_a32[256];
extern const OpFn dynarec_ops_fpu_287_da_a16[256];
extern const OpFn dynarec_ops_fpu_287_da_a32[256];
extern const OpFn dynarec_ops_fpu_287_db_a16[256];
extern const OpFn dynarec_ops_fpu_287_db_a32[256];
extern const OpFn dynarec_ops_fpu_287_dc_a16[32];
extern const OpFn dynarec_ops_fpu_287_dc_a32[32];
extern const OpFn dynarec_ops_fpu_287_dd_a16[256];
extern const OpFn dynarec_ops_fpu_287_dd_a32[256];
extern const OpFn dynarec_ops_fpu_287_de_a16[256];
extern const OpFn dynarec_ops_fpu_287_de_a32[256];
extern const OpFn dynarec_ops_fpu_287_df_a16[256];
extern const OpFn dynarec_ops_fpu_287_df_a32[256];
extern const OpFn dynarec_ops_fpu_d8_a16[32];
extern const OpFn dynarec_ops_fpu_d8_a32[32];
extern const OpFn dynarec_ops_fpu_d9_a16[256];
extern const OpFn dynarec_ops_fpu_d9_a32[256];
extern const OpFn dynarec_ops_fpu_da_a16[256];
extern const OpFn dynarec_ops_fpu_da_a32[256];
extern const OpFn dynarec_ops_fpu_db_a16[256];
extern const OpFn dynarec_ops_fpu_db_a32[256];
extern const OpFn dynarec_ops_fpu_dc_a16[32];
extern const OpFn dynarec_ops_fpu_dc_a32[32];
extern const OpFn dynarec_ops_fpu_dd_a16[256];
extern const OpFn dynarec_ops_fpu_dd_a32[256];
extern const OpFn dynarec_ops_fpu_de_a16[256];
extern const OpFn dynarec_ops_fpu_de_a32[256];
extern const OpFn dynarec_ops_fpu_df_a16[256];
extern const OpFn dynarec_ops_fpu_df_a32[256];
extern const OpFn dynarec_ops_nofpu_a16[256];
extern const OpFn dynarec_ops_nofpu_a32[256];
extern const OpFn dynarec_ops_fpu_686_da_a16[256];
extern const OpFn dynarec_ops_fpu_686_da_a32[256];
extern const OpFn dynarec_ops_fpu_686_db_a16[256];
extern const OpFn dynarec_ops_fpu_686_db_a32[256];
extern const OpFn dynarec_ops_fpu_686_df_a16[256];
extern const OpFn dynarec_ops_fpu_686_df_a32[256];
extern const OpFn dynarec_ops_REPE[1024];
extern const OpFn dynarec_ops_REPNE[1024];
#else
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
#endif
extern const OpFn *x86_opcodes;
extern const OpFn *x86_opcodes_0f;
extern const OpFn *x86_opcodes_d8_a16;
extern const OpFn *x86_opcodes_d8_a32;
extern const OpFn *x86_opcodes_d9_a16;
extern const OpFn *x86_opcodes_d9_a32;
extern const OpFn *x86_opcodes_da_a16;
extern const OpFn *x86_opcodes_da_a32;
extern const OpFn *x86_opcodes_db_a16;
extern const OpFn *x86_opcodes_db_a32;
extern const OpFn *x86_opcodes_dc_a16;
extern const OpFn *x86_opcodes_dc_a32;
extern const OpFn *x86_opcodes_dd_a16;
extern const OpFn *x86_opcodes_dd_a32;
extern const OpFn *x86_opcodes_de_a16;
extern const OpFn *x86_opcodes_de_a32;
extern const OpFn *x86_opcodes_df_a16;
extern const OpFn *x86_opcodes_df_a32;
extern const OpFn *x86_opcodes_REPE;
extern const OpFn *x86_opcodes_REPNE;
extern const OpFn ops_286[1024];
extern const OpFn ops_286_0f[1024];
extern const OpFn ops_386[1024];
extern const OpFn ops_386_0f[1024];
extern const OpFn ops_486_0f[1024];
extern const OpFn ops_winchip_0f[1024];
extern const OpFn ops_pentium_0f[1024];
extern const OpFn ops_pentiummmx_0f[1024];
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
extern const OpFn ops_c6x86mx_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_AMD_K)
extern const OpFn ops_k6_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_I686)
extern const OpFn ops_pentiumpro_0f[1024];
extern const OpFn ops_pentium2d_0f[1024];
#endif
extern const OpFn ops_fpu_287_d9_a16[256];
extern const OpFn ops_fpu_287_d9_a32[256];
extern const OpFn ops_fpu_287_da_a16[256];
extern const OpFn ops_fpu_287_da_a32[256];
extern const OpFn ops_fpu_287_db_a16[256];
extern const OpFn ops_fpu_287_db_a32[256];
extern const OpFn ops_fpu_287_dc_a16[32];
extern const OpFn ops_fpu_287_dc_a32[32];
extern const OpFn ops_fpu_287_dd_a16[256];
extern const OpFn ops_fpu_287_dd_a32[256];
extern const OpFn ops_fpu_287_de_a16[256];
extern const OpFn ops_fpu_287_de_a32[256];
extern const OpFn ops_fpu_287_df_a16[256];
extern const OpFn ops_fpu_287_df_a32[256];
extern const OpFn ops_fpu_d8_a16[32];
extern const OpFn ops_fpu_d8_a32[32];
extern const OpFn ops_fpu_d9_a16[256];
extern const OpFn ops_fpu_d9_a32[256];
extern const OpFn ops_fpu_da_a16[256];
extern const OpFn ops_fpu_da_a32[256];
extern const OpFn ops_fpu_db_a16[256];
extern const OpFn ops_fpu_db_a32[256];
extern const OpFn ops_fpu_dc_a16[32];
extern const OpFn ops_fpu_dc_a32[32];
extern const OpFn ops_fpu_dd_a16[256];
extern const OpFn ops_fpu_dd_a32[256];
extern const OpFn ops_fpu_de_a16[256];
extern const OpFn ops_fpu_de_a32[256];
extern const OpFn ops_fpu_df_a16[256];
extern const OpFn ops_fpu_df_a32[256];
extern const OpFn ops_nofpu_a16[256];
extern const OpFn ops_nofpu_a32[256];
extern const OpFn ops_fpu_686_da_a16[256];
extern const OpFn ops_fpu_686_da_a32[256];
extern const OpFn ops_fpu_686_db_a16[256];
extern const OpFn ops_fpu_686_db_a32[256];
extern const OpFn ops_fpu_686_df_a16[256];
extern const OpFn ops_fpu_686_df_a32[256];
extern const OpFn ops_REPE[1024];
extern const OpFn ops_REPNE[1024];
#endif /*_X86_OPS_H*/

View File

@@ -1,816 +0,0 @@
#define OP_ARITH(name, operation, setflags, flagops, gettempc) \
static int op ## name ## _b_rmw_a16(uint32_t fetchdat) \
{ \
uint8_t dst; \
uint8_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = getr8(cpu_rm); \
src = getr8(cpu_reg); \
setflags ## 8 flagops; \
setr8(cpu_rm, operation); \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteab(); if (cpu_state.abrt) return 1; \
src = getr8(cpu_reg); \
seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \
} \
return 0; \
} \
static int op ## name ## _b_rmw_a32(uint32_t fetchdat) \
{ \
uint8_t dst; \
uint8_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = getr8(cpu_rm); \
src = getr8(cpu_reg); \
setflags ## 8 flagops; \
setr8(cpu_rm, operation); \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteab(); if (cpu_state.abrt) return 1; \
src = getr8(cpu_reg); \
seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 1); \
} \
return 0; \
} \
\
static int op ## name ## _w_rmw_a16(uint32_t fetchdat) \
{ \
uint16_t dst; \
uint16_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].w; \
src = cpu_state.regs[cpu_reg].w; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_rm].w = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteaw(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 0); \
} \
return 0; \
} \
static int op ## name ## _w_rmw_a32(uint32_t fetchdat) \
{ \
uint16_t dst; \
uint16_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].w; \
src = cpu_state.regs[cpu_reg].w; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_rm].w = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteaw(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 1); \
} \
return 0; \
} \
\
static int op ## name ## _l_rmw_a16(uint32_t fetchdat) \
{ \
uint32_t dst; \
uint32_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].l; \
src = cpu_state.regs[cpu_reg].l; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_rm].l = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteal(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 0); \
} \
return 0; \
} \
static int op ## name ## _l_rmw_a32(uint32_t fetchdat) \
{ \
uint32_t dst; \
uint32_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].l; \
src = cpu_state.regs[cpu_reg].l; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_rm].l = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
dst = geteal(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 1); \
} \
return 0; \
} \
\
static int op ## name ## _b_rm_a16(uint32_t fetchdat) \
{ \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
setr8(cpu_reg, operation); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \
return 0; \
} \
static int op ## name ## _b_rm_a32(uint32_t fetchdat) \
{ \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
setr8(cpu_reg, operation); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _w_rm_a16(uint32_t fetchdat) \
{ \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_reg].w = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \
return 0; \
} \
static int op ## name ## _w_rm_a32(uint32_t fetchdat) \
{ \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_reg].w = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _l_rm_a16(uint32_t fetchdat) \
{ \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_reg].l = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); \
return 0; \
} \
static int op ## name ## _l_rm_a32(uint32_t fetchdat) \
{ \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_reg].l = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _AL_imm(uint32_t fetchdat) \
{ \
uint8_t dst = AL; \
uint8_t src = getbytef(); \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 8 flagops; \
AL = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int op ## name ## _AX_imm(uint32_t fetchdat) \
{ \
uint16_t dst = AX; \
uint16_t src = getwordf(); \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 16 flagops; \
AX = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int op ## name ## _EAX_imm(uint32_t fetchdat) \
{ \
uint32_t dst = EAX; \
uint32_t src = getlong(); if (cpu_state.abrt) return 1; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 32 flagops; \
EAX = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); \
return 0; \
}
OP_ARITH(ADD, dst + src, setadd, (dst, src), 0)
OP_ARITH(ADC, dst + src + tempc, setadc, (dst, src), 1)
OP_ARITH(SUB, dst - src, setsub, (dst, src), 0)
OP_ARITH(SBB, dst - (src + tempc), setsbc, (dst, src), 1)
OP_ARITH(OR, dst | src, setznp, (dst | src), 0)
OP_ARITH(AND, dst & src, setznp, (dst & src), 0)
OP_ARITH(XOR, dst ^ src, setznp, (dst ^ src), 0)
static int opCMP_b_rmw_a16(uint32_t fetchdat)
{
uint8_t dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_b_rmw_a32(uint32_t fetchdat)
{
uint8_t dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_w_rmw_a16(uint32_t fetchdat)
{
uint16_t dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_w_rmw_a32(uint32_t fetchdat)
{
uint16_t dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_l_rmw_a16(uint32_t fetchdat)
{
uint32_t dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opCMP_l_rmw_a32(uint32_t fetchdat)
{
uint32_t dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opCMP_b_rm_a16(uint32_t fetchdat)
{
uint8_t src;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_b_rm_a32(uint32_t fetchdat)
{
uint8_t src;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_w_rm_a16(uint32_t fetchdat)
{
uint16_t src;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_w_rm_a32(uint32_t fetchdat)
{
uint16_t src;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_l_rm_a16(uint32_t fetchdat)
{
uint32_t src;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opCMP_l_rm_a32(uint32_t fetchdat)
{
uint32_t src;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opCMP_AL_imm(uint32_t fetchdat)
{
uint8_t src = getbytef();
setsub8(AL, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opCMP_AX_imm(uint32_t fetchdat)
{
uint16_t src = getwordf();
setsub16(AX, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
return 0;
}
static int opCMP_EAX_imm(uint32_t fetchdat)
{
uint32_t src = getlong(); if (cpu_state.abrt) return 1;
setsub32(EAX, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_b_a16(uint32_t fetchdat)
{
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opTEST_b_a32(uint32_t fetchdat)
{
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opTEST_w_a16(uint32_t fetchdat)
{
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opTEST_w_a32(uint32_t fetchdat)
{
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opTEST_l_a16(uint32_t fetchdat)
{
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opTEST_l_a32(uint32_t fetchdat)
{
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opTEST_AL(uint32_t fetchdat)
{
uint8_t temp = getbytef();
setznp8(AL & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_AX(uint32_t fetchdat)
{
uint16_t temp = getwordf();
setznp16(AX & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_EAX(uint32_t fetchdat)
{
uint32_t temp = getlong(); if (cpu_state.abrt) return 1;
setznp32(EAX & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
return 0;
}
#define ARITH_MULTI(ea_width, flag_width) \
dst = getea ## ea_width(); if (cpu_state.abrt) return 1; \
switch (rmdat&0x38) \
{ \
case 0x00: /*ADD ea, #*/ \
setea ## ea_width(dst + src); if (cpu_state.abrt) return 1; \
setadd ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x08: /*OR ea, #*/ \
dst |= src; \
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x10: /*ADC ea, #*/ \
tempc = CF_SET() ? 1 : 0; \
setea ## ea_width(dst + src + tempc); if (cpu_state.abrt) return 1; \
setadc ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x18: /*SBB ea, #*/ \
tempc = CF_SET() ? 1 : 0; \
setea ## ea_width(dst - (src + tempc)); if (cpu_state.abrt) return 1; \
setsbc ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x20: /*AND ea, #*/ \
dst &= src; \
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x28: /*SUB ea, #*/ \
setea ## ea_width(dst - src); if (cpu_state.abrt) return 1; \
setsub ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x30: /*XOR ea, #*/ \
dst ^= src; \
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x38: /*CMP ea, #*/ \
setsub ## flag_width(dst, src); \
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); \
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 7); \
break; \
}
static int op80_a16(uint32_t fetchdat)
{
uint8_t src, dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(b, 8);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op80_a32(uint32_t fetchdat)
{
uint8_t src, dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(b, 8);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op81_w_a16(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op81_w_a32(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op81_l_a16(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_16(fetchdat);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int op81_l_a32(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}
static int op83_w_a16(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op83_w_a32(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op83_l_a16(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int op83_l_a32(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}

View File

@@ -1,752 +0,0 @@
#define OP_ARITH(name, operation, setflags, flagops, gettempc) \
static int op ## name ## _b_rmw_a16(uint32_t fetchdat) \
{ \
uint8_t dst; \
uint8_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = getr8(cpu_rm); \
src = getr8(cpu_reg); \
setflags ## 8 flagops; \
setr8(cpu_rm, operation); \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
dst = geteab(); if (cpu_state.abrt) return 1; \
src = getr8(cpu_reg); \
seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \
} \
return 0; \
} \
static int op ## name ## _b_rmw_a32(uint32_t fetchdat) \
{ \
uint8_t dst; \
uint8_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = getr8(cpu_rm); \
src = getr8(cpu_reg); \
setflags ## 8 flagops; \
setr8(cpu_rm, operation); \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
dst = geteab(); if (cpu_state.abrt) return 1; \
src = getr8(cpu_reg); \
seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 1); \
} \
return 0; \
} \
\
static int op ## name ## _w_rmw_a16(uint32_t fetchdat) \
{ \
uint16_t dst; \
uint16_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].w; \
src = cpu_state.regs[cpu_reg].w; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_rm].w = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
dst = geteaw(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 0); \
} \
return 0; \
} \
static int op ## name ## _w_rmw_a32(uint32_t fetchdat) \
{ \
uint16_t dst; \
uint16_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].w; \
src = cpu_state.regs[cpu_reg].w; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_rm].w = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
dst = geteaw(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 1); \
} \
return 0; \
} \
\
static int op ## name ## _l_rmw_a16(uint32_t fetchdat) \
{ \
uint32_t dst; \
uint32_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].l; \
src = cpu_state.regs[cpu_reg].l; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_rm].l = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
} \
else \
{ \
dst = geteal(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 0); \
} \
return 0; \
} \
static int op ## name ## _l_rmw_a32(uint32_t fetchdat) \
{ \
uint32_t dst; \
uint32_t src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
if (cpu_mod == 3) \
{ \
dst = cpu_state.regs[cpu_rm].l; \
src = cpu_state.regs[cpu_reg].l; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_rm].l = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
} \
else \
{ \
dst = geteal(); if (cpu_state.abrt) return 1; \
src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 1); \
} \
return 0; \
} \
\
static int op ## name ## _b_rm_a16(uint32_t fetchdat) \
{ \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
setr8(cpu_reg, operation); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \
return 0; \
} \
static int op ## name ## _b_rm_a32(uint32_t fetchdat) \
{ \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
setr8(cpu_reg, operation); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _w_rm_a16(uint32_t fetchdat) \
{ \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_reg].w = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0); \
return 0; \
} \
static int op ## name ## _w_rm_a32(uint32_t fetchdat) \
{ \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
cpu_state.regs[cpu_reg].w = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _l_rm_a16(uint32_t fetchdat) \
{ \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_reg].l = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0); \
return 0; \
} \
static int op ## name ## _l_rm_a32(uint32_t fetchdat) \
{ \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
cpu_state.regs[cpu_reg].l = operation; \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml); \
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1); \
return 0; \
} \
\
static int op ## name ## _AL_imm(uint32_t fetchdat) \
{ \
uint8_t dst = AL; \
uint8_t src = getbytef(); \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 8 flagops; \
AL = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int op ## name ## _AX_imm(uint32_t fetchdat) \
{ \
uint16_t dst = AX; \
uint16_t src = getwordf(); \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 16 flagops; \
AX = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int op ## name ## _EAX_imm(uint32_t fetchdat) \
{ \
uint32_t dst = EAX; \
uint32_t src = getlong(); if (cpu_state.abrt) return 1; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
setflags ## 32 flagops; \
EAX = operation; \
CLOCK_CYCLES(timing_rr); \
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); \
return 0; \
}
OP_ARITH(ADD, dst + src, setadd, (dst, src), 0)
OP_ARITH(ADC, dst + src + tempc, setadc, (dst, src), 1)
OP_ARITH(SUB, dst - src, setsub, (dst, src), 0)
OP_ARITH(SBB, dst - (src + tempc), setsbc, (dst, src), 1)
OP_ARITH(OR, dst | src, setznp, (dst | src), 0)
OP_ARITH(AND, dst & src, setznp, (dst & src), 0)
OP_ARITH(XOR, dst ^ src, setznp, (dst ^ src), 0)
static int opCMP_b_rmw_a16(uint32_t fetchdat)
{
uint8_t dst;
fetch_ea_16(fetchdat);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_b_rmw_a32(uint32_t fetchdat)
{
uint8_t dst;
fetch_ea_32(fetchdat);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_w_rmw_a16(uint32_t fetchdat)
{
uint16_t dst;
fetch_ea_16(fetchdat);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_w_rmw_a32(uint32_t fetchdat)
{
uint16_t dst;
fetch_ea_32(fetchdat);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_l_rmw_a16(uint32_t fetchdat)
{
uint32_t dst;
fetch_ea_16(fetchdat);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opCMP_l_rmw_a32(uint32_t fetchdat)
{
uint32_t dst;
fetch_ea_32(fetchdat);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opCMP_b_rm_a16(uint32_t fetchdat)
{
uint8_t src;
fetch_ea_16(fetchdat);
src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_b_rm_a32(uint32_t fetchdat)
{
uint8_t src;
fetch_ea_32(fetchdat);
src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_w_rm_a16(uint32_t fetchdat)
{
uint16_t src;
fetch_ea_16(fetchdat);
src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opCMP_w_rm_a32(uint32_t fetchdat)
{
uint16_t src;
fetch_ea_32(fetchdat);
src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opCMP_l_rm_a16(uint32_t fetchdat)
{
uint32_t src;
fetch_ea_16(fetchdat);
src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opCMP_l_rm_a32(uint32_t fetchdat)
{
uint32_t src;
fetch_ea_32(fetchdat);
src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opCMP_AL_imm(uint32_t fetchdat)
{
uint8_t src = getbytef();
setsub8(AL, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opCMP_AX_imm(uint32_t fetchdat)
{
uint16_t src = getwordf();
setsub16(AX, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
return 0;
}
static int opCMP_EAX_imm(uint32_t fetchdat)
{
uint32_t src = getlong(); if (cpu_state.abrt) return 1;
setsub32(EAX, src);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_b_a16(uint32_t fetchdat)
{
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opTEST_b_a32(uint32_t fetchdat)
{
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opTEST_w_a16(uint32_t fetchdat)
{
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
return 0;
}
static int opTEST_w_a32(uint32_t fetchdat)
{
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
return 0;
}
static int opTEST_l_a16(uint32_t fetchdat)
{
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 0);
return 0;
}
static int opTEST_l_a32(uint32_t fetchdat)
{
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 1);
return 0;
}
static int opTEST_AL(uint32_t fetchdat)
{
uint8_t temp = getbytef();
setznp8(AL & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_AX(uint32_t fetchdat)
{
uint16_t temp = getwordf();
setznp16(AX & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
return 0;
}
static int opTEST_EAX(uint32_t fetchdat)
{
uint32_t temp = getlong(); if (cpu_state.abrt) return 1;
setznp32(EAX & temp);
CLOCK_CYCLES(timing_rr);
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
return 0;
}
#define ARITH_MULTI(ea_width, flag_width, is32) \
dst = read ## ea_width(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \
switch ((rmdat >> 3) & 7) \
{ \
case 0x00: /*ADD ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
write ## ea_width(easeg, cpu_state.eaaddr, dst + src); if (cpu_state.abrt) return 1; \
setadd ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x01: /*OR ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
dst |= src; \
write ## ea_width(easeg, cpu_state.eaaddr, dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x02: /*ADC ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
tempc = CF_SET() ? 1 : 0; \
write ## ea_width(easeg, cpu_state.eaaddr, dst + src + tempc); if (cpu_state.abrt) return 1; \
setadc ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x03: /*SBB ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
tempc = CF_SET() ? 1 : 0; \
write ## ea_width(easeg, cpu_state.eaaddr, dst - (src + tempc)); if (cpu_state.abrt) return 1; \
setsbc ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x04: /*AND ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
dst &= src; \
write ## ea_width(easeg, cpu_state.eaaddr, dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x05: /*SUB ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
write ## ea_width(easeg, cpu_state.eaaddr, dst - src); if (cpu_state.abrt) return 1; \
setsub ## flag_width(dst, src); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x06: /*XOR ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 1, is32) \
dst ^= src; \
write ## ea_width(easeg, cpu_state.eaaddr, dst); if (cpu_state.abrt) return 1; \
setznp ## flag_width(dst); \
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
break; \
case 0x07: /*CMP ea, #*/ \
if (cpu_mod != 3) x86_translate_break(cpu_state.ea_seg, cpu_state.eaaddr, 0, is32) \
setsub ## flag_width(dst, src); \
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); \
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 7); \
break; \
}
static int op80_a16(uint32_t fetchdat)
{
uint8_t src, dst;
fetch_ea_16(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(8, 8, 0);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op80_a32(uint32_t fetchdat)
{
uint8_t src, dst;
fetch_ea_32(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(8, 8, 1);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op81_w_a16(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_16(fetchdat);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(16, 16, 0);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op81_w_a32(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_32(fetchdat);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(16, 16, 1);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op81_l_a16(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_16(fetchdat);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(32, 32, 0);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int op81_l_a32(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_32(fetchdat);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(32, 32, 1);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}
static int op83_w_a16(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_16(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(16, 16, 0);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int op83_w_a32(uint32_t fetchdat)
{
uint16_t src, dst;
fetch_ea_32(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(16, 16, 1);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int op83_l_a16(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_16(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(32, 32, 0);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int op83_l_a32(uint32_t fetchdat)
{
uint32_t src, dst;
fetch_ea_32(fetchdat);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(32, 32, 1);
if ((rmdat & 0x38) == 0x38)
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
else
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}

View File

@@ -1,292 +0,0 @@
static int opCMPXCHG_b_a16(uint32_t fetchdat)
{
uint8_t temp, temp2 = AL;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
if (AL == temp) seteab(getr8(cpu_reg));
else AL = temp;
if (cpu_state.abrt) return 1;
setsub8(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG_b_a32(uint32_t fetchdat)
{
uint8_t temp, temp2 = AL;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
if (AL == temp) seteab(getr8(cpu_reg));
else AL = temp;
if (cpu_state.abrt) return 1;
setsub8(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG_w_a16(uint32_t fetchdat)
{
uint16_t temp, temp2 = AX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w);
else AX = temp;
if (cpu_state.abrt) return 1;
setsub16(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG_w_a32(uint32_t fetchdat)
{
uint16_t temp, temp2 = AX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w);
else AX = temp;
if (cpu_state.abrt) return 1;
setsub16(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG_l_a16(uint32_t fetchdat)
{
uint32_t temp, temp2 = EAX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l);
else EAX = temp;
if (cpu_state.abrt) return 1;
setsub32(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG_l_a32(uint32_t fetchdat)
{
uint32_t temp, temp2 = EAX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l);
else EAX = temp;
if (cpu_state.abrt) return 1;
setsub32(temp2, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
return 0;
}
static int opCMPXCHG8B_a16(uint32_t fetchdat)
{
uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
if (EAX == temp && EDX == temp_hi)
{
seteal(EBX);
writememl(easeg, cpu_state.eaaddr+4, ECX);
}
else
{
EAX = temp;
EDX = temp_hi;
}
if (cpu_state.abrt) return 0;
flags_rebuild();
if (temp == temp2 && temp_hi == temp2_hi)
cpu_state.flags |= Z_FLAG;
else
cpu_state.flags &= ~Z_FLAG;
cycles -= (cpu_mod == 3) ? 6 : 10;
return 0;
}
static int opCMPXCHG8B_a32(uint32_t fetchdat)
{
uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
if (EAX == temp && EDX == temp_hi)
{
seteal(EBX);
writememl(easeg, cpu_state.eaaddr+4, ECX);
}
else
{
EAX = temp;
EDX = temp_hi;
}
if (cpu_state.abrt) return 0;
flags_rebuild();
if (temp == temp2 && temp_hi == temp2_hi)
cpu_state.flags |= Z_FLAG;
else
cpu_state.flags &= ~Z_FLAG;
cycles -= (cpu_mod == 3) ? 6 : 10;
return 0;
}
static int opXADD_b_a16(uint32_t fetchdat)
{
uint8_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setadd8(temp, getr8(cpu_reg));
setr8(cpu_reg, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}
static int opXADD_b_a32(uint32_t fetchdat)
{
uint8_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setadd8(temp, getr8(cpu_reg));
setr8(cpu_reg, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}
static int opXADD_w_a16(uint32_t fetchdat)
{
uint16_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
setadd16(temp, cpu_state.regs[cpu_reg].w);
cpu_state.regs[cpu_reg].w = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}
static int opXADD_w_a32(uint32_t fetchdat)
{
uint16_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
setadd16(temp, cpu_state.regs[cpu_reg].w);
cpu_state.regs[cpu_reg].w = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}
static int opXADD_l_a16(uint32_t fetchdat)
{
uint32_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_16(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
setadd32(temp, cpu_state.regs[cpu_reg].l);
cpu_state.regs[cpu_reg].l = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}
static int opXADD_l_a32(uint32_t fetchdat)
{
uint32_t temp;
if (!is486)
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
fetch_ea_32(fetchdat);
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
setadd32(temp, cpu_state.regs[cpu_reg].l);
cpu_state.regs[cpu_reg].l = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
return 0;
}

View File

@@ -1,332 +0,0 @@
static int opBT_w_r_a16(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_16(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0;
temp = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0);
return 0;
}
static int opBT_w_r_a32(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_32(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0;
temp = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1);
return 0;
}
static int opBT_l_r_a16(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_16(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0;
temp = geteal(); if (cpu_state.abrt) return 1;
flags_rebuild();
if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0);
return 0;
}
static int opBT_l_r_a32(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_32(fetchdat);
SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0;
temp = geteal(); if (cpu_state.abrt) return 1;
flags_rebuild();
if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1);
return 0;
}
#define opBT(name, operation) \
static int opBT ## name ## _w_r_a16(uint32_t fetchdat) \
{ \
int tempc; \
uint16_t temp; \
\
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \
temp = geteaw(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \
seteaw(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \
return 0; \
} \
static int opBT ## name ## _w_r_a32(uint32_t fetchdat) \
{ \
int tempc; \
uint16_t temp; \
\
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \
temp = geteaw(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \
seteaw(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \
return 0; \
} \
static int opBT ## name ## _l_r_a16(uint32_t fetchdat) \
{ \
int tempc; \
uint32_t temp; \
\
fetch_ea_16(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \
temp = geteal(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \
seteal(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \
return 0; \
} \
static int opBT ## name ## _l_r_a32(uint32_t fetchdat) \
{ \
int tempc; \
uint32_t temp; \
\
fetch_ea_32(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \
temp = geteal(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \
seteal(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
if (tempc) cpu_state.flags |= C_FLAG; \
else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \
return 0; \
}
opBT(C, ^=)
opBT(R, &=~)
opBT(S, |=)
static int opBA_w_a16(uint32_t fetchdat)
{
int tempc, count;
uint16_t temp;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
flags_rebuild();
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
return 0;
case 0x28: /*BTS w,imm*/
temp |= (1 << count);
break;
case 0x30: /*BTR w,imm*/
temp &= ~(1 << count);
break;
case 0x38: /*BTC w,imm*/
temp ^= (1 << count);
break;
default:
x386_dynarec_log("Bad 0F BA opcode %02X\n", rmdat & 0x38);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
seteaw(temp); if (cpu_state.abrt) return 1;
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int opBA_w_a32(uint32_t fetchdat)
{
int tempc, count;
uint16_t temp;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
flags_rebuild();
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
return 0;
case 0x28: /*BTS w,imm*/
temp |= (1 << count);
break;
case 0x30: /*BTR w,imm*/
temp &= ~(1 << count);
break;
case 0x38: /*BTC w,imm*/
temp ^= (1 << count);
break;
default:
x386_dynarec_log("Bad 0F BA opcode %02X\n", rmdat & 0x38);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
seteaw(temp); if (cpu_state.abrt) return 1;
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int opBA_l_a16(uint32_t fetchdat)
{
int tempc, count;
uint32_t temp;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
flags_rebuild();
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
return 0;
case 0x28: /*BTS w,imm*/
temp |= (1 << count);
break;
case 0x30: /*BTR w,imm*/
temp &= ~(1 << count);
break;
case 0x38: /*BTC w,imm*/
temp ^= (1 << count);
break;
default:
x386_dynarec_log("Bad 0F BA opcode %02X\n", rmdat & 0x38);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
seteal(temp); if (cpu_state.abrt) return 1;
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int opBA_l_a32(uint32_t fetchdat)
{
int tempc, count;
uint32_t temp;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
flags_rebuild();
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
return 0;
case 0x28: /*BTS w,imm*/
temp |= (1 << count);
break;
case 0x30: /*BTR w,imm*/
temp &= ~(1 << count);
break;
case 0x38: /*BTC w,imm*/
temp ^= (1 << count);
break;
default:
x386_dynarec_log("Bad 0F BA opcode %02X\n", rmdat & 0x38);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
seteal(temp); if (cpu_state.abrt) return 1;
if (tempc) cpu_state.flags |= C_FLAG;
else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}

View File

@@ -1,508 +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.
*
* x86 i686 (Pentium Pro/Pentium II) CPU Instructions.
*
* Version: @(#)x86_ops_i686.h 1.0.5 2018/10/17
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
*/
/* 0 = Limit 0-15
1 = Base 0-15
2 = Base 16-23 (bits 0-7), Access rights
8-11 Type
12 S
13, 14 DPL
15 P
3 = Limit 16-19 (bits 0-3), Base 24-31 (bits 8-15), granularity, etc.
4 A
6 DB
7 G */
static void make_seg_data(uint16_t *seg_data, uint32_t base, uint32_t limit, uint8_t type, uint8_t s, uint8_t dpl, uint8_t p, uint8_t g, uint8_t db, uint8_t a)
{
seg_data[0] = limit & 0xFFFF;
seg_data[1] = base & 0xFFFF;
seg_data[2] = ((base >> 16) & 0xFF) | (type << 8) | (p << 15) | (dpl << 13) | (s << 12);
seg_data[3] = ((limit >> 16) & 0xF) | (a << 4) | (db << 6) | (g << 7) | ((base >> 16) & 0xFF00);
}
static int opSYSENTER(uint32_t fetchdat)
{
uint16_t sysenter_cs_seg_data[4];
uint16_t sysenter_ss_seg_data[4];
#ifdef SYSENTER_LOG
x386_dynarec_log("SYSENTER called\n");
#endif
if (!(msw & 1)) return internal_illegal("SYSENTER: CPU not in protected mode");
if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSENTER: CS MSR is zero");
#ifdef SYSENTER_LOG
x386_dynarec_log("SYSENTER started:\n");
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32);
#endif
if (cpu_state.abrt) return 1;
ESP = esp_msr;
cpu_state.pc = eip_msr;
optype = CALL; \
cgate16 = cgate32 = 0; \
/* Set VM, RF, and IF to 0. */
cpu_state.eflags &= ~(VM_FLAG | 0x0001);
cpu_state.flags &= ~I_FLAG;
CS = (cs_msr & 0xFFFC);
make_seg_data(sysenter_cs_seg_data, 0, 0xFFFFF, 11, 1, 0, 1, 1, 1, 0);
do_seg_load(&cpu_state.seg_cs, sysenter_cs_seg_data);
use32 = 0x300;
SS = ((cs_msr + 8) & 0xFFFC);
make_seg_data(sysenter_ss_seg_data, 0, 0xFFFFF, 3, 1, 0, 1, 1, 1, 0);
do_seg_load(&cpu_state.seg_ss, sysenter_ss_seg_data);
stack32 = 1;
cycles -= timing_call_pm;
optype = 0;
CPU_BLOCK_END();
#ifdef SYSENTER_LOG
x386_dynarec_log("SYSENTER completed:\n");
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32);
#endif
return 0;
}
static int opSYSEXIT(uint32_t fetchdat)
{
uint16_t sysexit_cs_seg_data[4];
uint16_t sysexit_ss_seg_data[4];
#ifdef SYSEXIT_LOG
x386_dynarec_log("SYSEXIT called\n");
#endif
if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSEXIT: CS MSR is zero");
if (!(msw & 1)) return internal_illegal("SYSEXIT: CPU not in protected mode");
if (CPL) return internal_illegal("SYSEXIT: CPL not 0");
#ifdef SYSEXIT_LOG
x386_dynarec_log("SYSEXIT start:\n");
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32, ECX, EDX);
#endif
if (cpu_state.abrt) return 1;
ESP = ECX;
cpu_state.pc = EDX;
optype = CALL; \
cgate16 = cgate32 = 0; \
CS = ((cs_msr + 16) & 0xFFFC) | 3;
make_seg_data(sysexit_cs_seg_data, 0, 0xFFFFF, 11, 1, 3, 1, 1, 1, 0);
do_seg_load(&cpu_state.seg_cs, sysexit_cs_seg_data);
use32 = 0x300;
SS = CS + 8;
make_seg_data(sysexit_ss_seg_data, 0, 0xFFFFF, 3, 1, 3, 1, 1, 1, 0);
do_seg_load(&cpu_state.seg_ss, sysexit_ss_seg_data);
stack32 = 1;
flushmmucache_cr3();
cycles -= timing_call_pm;
optype = 0;
CPU_BLOCK_END();
#ifdef SYSEXIT_LOG
x386_dynarec_log("SYSEXIT completed:\n");
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32, ECX, EDX);
#endif
return 0;
}
static int opFXSAVESTOR_a16(uint32_t fetchdat)
{
uint8_t fxinst = 0;
uint16_t twd = x87_gettag();
uint16_t old_eaaddr = 0;
uint8_t ftwb = 0;
uint16_t rec_ftw = 0;
uint16_t fpus = 0;
uint64_t *p;
if (CPUID < 0x650) return ILLEGAL(fetchdat);
FP_ENTER();
fetch_ea_16(fetchdat);
if (cpu_state.eaaddr & 0xf)
{
x386_dynarec_log("Effective address %04X not on 16-byte boundary\n", cpu_state.eaaddr);
x86gpf(NULL, 0);
return cpu_state.abrt;
}
fxinst = (rmdat >> 3) & 7;
if ((fxinst > 1) || (cpu_mod == 3))
{
x86illegal();
return cpu_state.abrt;
}
FP_ENTER();
old_eaaddr = cpu_state.eaaddr;
if (fxinst == 1)
{
/* FXRSTOR */
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
cpu_state.TOP = (fpus >> 11) & 7;
cpu_state.npxs &= fpus & ~0x3800;
/* foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; */
x87_pc_off = readmeml(easeg, cpu_state.eaaddr+8);
x87_pc_seg = readmemw(easeg, cpu_state.eaaddr+12);
/* if (cr0 & 1)
{
x87_pc_seg &= 0xFFFC;
x87_pc_seg |= ((cpu_state.seg_cs.access >> 5) & 3);
} */
ftwb = readmemb(easeg, cpu_state.eaaddr + 4);
if (ftwb & 0x01) rec_ftw |= 0x0003;
if (ftwb & 0x02) rec_ftw |= 0x000C;
if (ftwb & 0x04) rec_ftw |= 0x0030;
if (ftwb & 0x08) rec_ftw |= 0x00C0;
if (ftwb & 0x10) rec_ftw |= 0x0300;
if (ftwb & 0x20) rec_ftw |= 0x0C00;
if (ftwb & 0x40) rec_ftw |= 0x3000;
if (ftwb & 0x80) rec_ftw |= 0xC000;
x87_op_off = readmeml(easeg, cpu_state.eaaddr+16);
x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16;
x87_op_seg = readmemw(easeg, cpu_state.eaaddr+20);
/* if (cr0 & 1)
{
x87_op_seg &= 0xFFFC;
x87_op_seg |= ((_ds.access >> 5) & 3);
} */
cpu_state.eaaddr = old_eaaddr + 32;
x87_ldmmx(&(cpu_state.MM[0]), &(cpu_state.MM_w4[0])); x87_ld_frstor(0);
cpu_state.eaaddr = old_eaaddr + 48;
x87_ldmmx(&(cpu_state.MM[1]), &(cpu_state.MM_w4[1])); x87_ld_frstor(1);
cpu_state.eaaddr = old_eaaddr + 64;
x87_ldmmx(&(cpu_state.MM[2]), &(cpu_state.MM_w4[2])); x87_ld_frstor(2);
cpu_state.eaaddr = old_eaaddr + 80;
x87_ldmmx(&(cpu_state.MM[3]), &(cpu_state.MM_w4[3])); x87_ld_frstor(3);
cpu_state.eaaddr = old_eaaddr + 96;
x87_ldmmx(&(cpu_state.MM[4]), &(cpu_state.MM_w4[4])); x87_ld_frstor(4);
cpu_state.eaaddr = old_eaaddr + 112;
x87_ldmmx(&(cpu_state.MM[5]), &(cpu_state.MM_w4[5])); x87_ld_frstor(5);
cpu_state.eaaddr = old_eaaddr + 128;
x87_ldmmx(&(cpu_state.MM[6]), &(cpu_state.MM_w4[6])); x87_ld_frstor(6);
cpu_state.eaaddr = old_eaaddr + 144;
x87_ldmmx(&(cpu_state.MM[7]), &(cpu_state.MM_w4[7])); x87_ld_frstor(7);
cpu_state.ismmx = 0;
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
something like this is needed*/
p = (uint64_t *)cpu_state.tag;
if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff &&
cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff &&
!cpu_state.TOP && !(*p))
cpu_state.ismmx = 1;
x87_settag(rec_ftw);
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
if(cpu_state.abrt) x386_dynarec_log("FXRSTOR: abrt != 0\n");
}
else
{
/* FXSAVE */
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememb(easeg,cpu_state.eaaddr+4,ftwb);
writememw(easeg,cpu_state.eaaddr+6,(x87_op_off>>16)<<12);
writememl(easeg,cpu_state.eaaddr+8,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+12,x87_pc_seg);
writememl(easeg,cpu_state.eaaddr+16,x87_op_off);
writememw(easeg,cpu_state.eaaddr+20,x87_op_seg);
cpu_state.eaaddr = old_eaaddr + 32;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[0]) : x87_st_fsave(0);
cpu_state.eaaddr = old_eaaddr + 48;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[1]) : x87_st_fsave(1);
cpu_state.eaaddr = old_eaaddr + 64;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[2]) : x87_st_fsave(2);
cpu_state.eaaddr = old_eaaddr + 80;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[3]) : x87_st_fsave(3);
cpu_state.eaaddr = old_eaaddr + 96;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[4]) : x87_st_fsave(4);
cpu_state.eaaddr = old_eaaddr + 112;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[5]) : x87_st_fsave(5);
cpu_state.eaaddr = old_eaaddr + 128;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[6]) : x87_st_fsave(6);
cpu_state.eaaddr = old_eaaddr + 144;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[7]) : x87_st_fsave(7);
cpu_state.eaaddr = old_eaaddr;
cpu_state.npxc = 0x37F;
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag;
*p = 0x0303030303030303ll;
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
if(cpu_state.abrt) x386_dynarec_log("FXSAVE: abrt != 0\n");
}
return cpu_state.abrt;
}
static int opFXSAVESTOR_a32(uint32_t fetchdat)
{
uint8_t fxinst = 0;
uint16_t twd = x87_gettag();
uint32_t old_eaaddr = 0;
uint8_t ftwb = 0;
uint16_t rec_ftw = 0;
uint16_t fpus = 0;
uint64_t *p;
if (CPUID < 0x650) return ILLEGAL(fetchdat);
FP_ENTER();
fetch_ea_32(fetchdat);
if (cpu_state.eaaddr & 0xf)
{
x386_dynarec_log("Effective address %08X not on 16-byte boundary\n", cpu_state.eaaddr);
x86gpf(NULL, 0);
return cpu_state.abrt;
}
fxinst = (rmdat >> 3) & 7;
if ((fxinst > 1) || (cpu_mod == 3))
{
x86illegal();
return cpu_state.abrt;
}
FP_ENTER();
old_eaaddr = cpu_state.eaaddr;
if (fxinst == 1)
{
/* FXRSTOR */
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
cpu_state.TOP = (fpus >> 11) & 7;
cpu_state.npxs &= fpus & ~0x3800;
/* foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; */
x87_pc_off = readmeml(easeg, cpu_state.eaaddr+8);
x87_pc_seg = readmemw(easeg, cpu_state.eaaddr+12);
/* if (cr0 & 1)
{
x87_pc_seg &= 0xFFFC;
x87_pc_seg |= ((cpu_state.seg_cs.access >> 5) & 3);
} */
ftwb = readmemb(easeg, cpu_state.eaaddr + 4);
if (ftwb & 0x01) rec_ftw |= 0x0003;
if (ftwb & 0x02) rec_ftw |= 0x000C;
if (ftwb & 0x04) rec_ftw |= 0x0030;
if (ftwb & 0x08) rec_ftw |= 0x00C0;
if (ftwb & 0x10) rec_ftw |= 0x0300;
if (ftwb & 0x20) rec_ftw |= 0x0C00;
if (ftwb & 0x40) rec_ftw |= 0x3000;
if (ftwb & 0x80) rec_ftw |= 0xC000;
x87_op_off = readmeml(easeg, cpu_state.eaaddr+16);
x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16;
x87_op_seg = readmemw(easeg, cpu_state.eaaddr+20);
/* if (cr0 & 1)
{
x87_op_seg &= 0xFFFC;
x87_op_seg |= ((_ds.access >> 5) & 3);
} */
cpu_state.eaaddr = old_eaaddr + 32;
x87_ldmmx(&(cpu_state.MM[0]), &(cpu_state.MM_w4[0])); x87_ld_frstor(0);
cpu_state.eaaddr = old_eaaddr + 48;
x87_ldmmx(&(cpu_state.MM[1]), &(cpu_state.MM_w4[1])); x87_ld_frstor(1);
cpu_state.eaaddr = old_eaaddr + 64;
x87_ldmmx(&(cpu_state.MM[2]), &(cpu_state.MM_w4[2])); x87_ld_frstor(2);
cpu_state.eaaddr = old_eaaddr + 80;
x87_ldmmx(&(cpu_state.MM[3]), &(cpu_state.MM_w4[3])); x87_ld_frstor(3);
cpu_state.eaaddr = old_eaaddr + 96;
x87_ldmmx(&(cpu_state.MM[4]), &(cpu_state.MM_w4[4])); x87_ld_frstor(4);
cpu_state.eaaddr = old_eaaddr + 112;
x87_ldmmx(&(cpu_state.MM[5]), &(cpu_state.MM_w4[5])); x87_ld_frstor(5);
cpu_state.eaaddr = old_eaaddr + 128;
x87_ldmmx(&(cpu_state.MM[6]), &(cpu_state.MM_w4[6])); x87_ld_frstor(6);
cpu_state.eaaddr = old_eaaddr + 144;
x87_ldmmx(&(cpu_state.MM[7]), &(cpu_state.MM_w4[7])); x87_ld_frstor(7);
cpu_state.ismmx = 0;
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
something like this is needed*/
p = (uint64_t *)cpu_state.tag;
if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff &&
cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff &&
!cpu_state.TOP && !(*p))
cpu_state.ismmx = 1;
x87_settag(rec_ftw);
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
if(cpu_state.abrt) x386_dynarec_log("FXRSTOR: abrt != 0\n");
}
else
{
/* FXSAVE */
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
writememb(easeg,cpu_state.eaaddr+4,ftwb);
writememw(easeg,cpu_state.eaaddr+6,(x87_op_off>>16)<<12);
writememl(easeg,cpu_state.eaaddr+8,x87_pc_off);
writememw(easeg,cpu_state.eaaddr+12,x87_pc_seg);
writememl(easeg,cpu_state.eaaddr+16,x87_op_off);
writememw(easeg,cpu_state.eaaddr+20,x87_op_seg);
cpu_state.eaaddr = old_eaaddr + 32;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[0]) : x87_st_fsave(0);
cpu_state.eaaddr = old_eaaddr + 48;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[1]) : x87_st_fsave(1);
cpu_state.eaaddr = old_eaaddr + 64;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[2]) : x87_st_fsave(2);
cpu_state.eaaddr = old_eaaddr + 80;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[3]) : x87_st_fsave(3);
cpu_state.eaaddr = old_eaaddr + 96;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[4]) : x87_st_fsave(4);
cpu_state.eaaddr = old_eaaddr + 112;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[5]) : x87_st_fsave(5);
cpu_state.eaaddr = old_eaaddr + 128;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[6]) : x87_st_fsave(6);
cpu_state.eaaddr = old_eaaddr + 144;
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[7]) : x87_st_fsave(7);
cpu_state.eaaddr = old_eaaddr;
cpu_state.npxc = 0x37F;
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag;
*p = 0x0303030303030303ll;
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
if(cpu_state.abrt) x386_dynarec_log("FXSAVE: abrt != 0\n");
}
return cpu_state.abrt;
}

View File

@@ -1,358 +0,0 @@
#define cond_O ( VF_SET())
#define cond_NO (!VF_SET())
#define cond_B ( CF_SET())
#define cond_NB (!CF_SET())
#define cond_E ( ZF_SET())
#define cond_NE (!ZF_SET())
#define cond_BE ( CF_SET() || ZF_SET())
#define cond_NBE (!CF_SET() && !ZF_SET())
#define cond_S ( NF_SET())
#define cond_NS (!NF_SET())
#define cond_P ( PF_SET())
#define cond_NP (!PF_SET())
#define cond_L (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0))
#define cond_NL (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0))
#define cond_LE (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0) || (ZF_SET()))
#define cond_NLE (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0) && (!ZF_SET()))
#define opJ(condition) \
static int opJ ## condition(uint32_t fetchdat) \
{ \
int8_t offset = (int8_t)getbytef(); \
CLOCK_CYCLES(timing_bnt); \
if (cond_ ## condition) \
{ \
cpu_state.pc += offset; \
CLOCK_CYCLES_ALWAYS(timing_bt); \
CPU_BLOCK_END(); \
PREFETCH_RUN(timing_bt+timing_bnt, 2, -1, 0,0,0,0, 0); \
PREFETCH_FLUSH(); \
return 1; \
} \
PREFETCH_RUN(timing_bnt, 2, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int opJ ## condition ## _w(uint32_t fetchdat) \
{ \
int16_t offset = (int16_t)getwordf(); \
CLOCK_CYCLES(timing_bnt); \
if (cond_ ## condition) \
{ \
cpu_state.pc += offset; \
CLOCK_CYCLES_ALWAYS(timing_bt); \
CPU_BLOCK_END(); \
PREFETCH_RUN(timing_bt+timing_bnt, 3, -1, 0,0,0,0, 0); \
PREFETCH_FLUSH(); \
return 1; \
} \
PREFETCH_RUN(timing_bnt, 3, -1, 0,0,0,0, 0); \
return 0; \
} \
\
static int opJ ## condition ## _l(uint32_t fetchdat) \
{ \
uint32_t offset = getlong(); if (cpu_state.abrt) return 1; \
CLOCK_CYCLES(timing_bnt); \
if (cond_ ## condition) \
{ \
cpu_state.pc += offset; \
CLOCK_CYCLES_ALWAYS(timing_bt); \
CPU_BLOCK_END(); \
PREFETCH_RUN(timing_bt+timing_bnt, 5, -1, 0,0,0,0, 0); \
PREFETCH_FLUSH(); \
return 1; \
} \
PREFETCH_RUN(timing_bnt, 5, -1, 0,0,0,0, 0); \
return 0; \
} \
opJ(O)
opJ(NO)
opJ(B)
opJ(NB)
opJ(E)
opJ(NE)
opJ(BE)
opJ(NBE)
opJ(S)
opJ(NS)
opJ(P)
opJ(NP)
opJ(L)
opJ(NL)
opJ(LE)
opJ(NLE)
static int opLOOPNE_w(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
CX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (CX && !ZF_SET())
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opLOOPNE_l(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
ECX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (ECX && !ZF_SET())
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opLOOPE_w(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
CX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (CX && ZF_SET())
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opLOOPE_l(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
ECX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (ECX && ZF_SET())
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opLOOP_w(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
CX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (CX)
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opLOOP_l(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
ECX--;
CLOCK_CYCLES((is486) ? 7 : 11);
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
if (ECX)
{
cpu_state.pc += offset;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
}
return 0;
}
static int opJCXZ(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
CLOCK_CYCLES(5);
if (!CX)
{
cpu_state.pc += offset;
CLOCK_CYCLES(4);
CPU_BLOCK_END();
PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 1;
}
PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opJECXZ(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
CLOCK_CYCLES(5);
if (!ECX)
{
cpu_state.pc += offset;
CLOCK_CYCLES(4);
CPU_BLOCK_END();
PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 1;
}
PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0);
return 0;
}
static int opJMP_r8(uint32_t fetchdat)
{
int8_t offset = (int8_t)getbytef();
cpu_state.pc += offset;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 2, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opJMP_r16(uint32_t fetchdat)
{
int16_t offset = (int16_t)getwordf();
cpu_state.pc += offset;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 3, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opJMP_r32(uint32_t fetchdat)
{
int32_t offset = (int32_t)getlong(); if (cpu_state.abrt) return 1;
cpu_state.pc += offset;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 5, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opJMP_far_a16(uint32_t fetchdat)
{
uint16_t addr, seg;
uint32_t old_pc;
addr = getwordf();
seg = getword(); if (cpu_state.abrt) return 1;
old_pc = cpu_state.pc;
cpu_state.pc = addr;
loadcsjmp(seg, old_pc);
CPU_BLOCK_END();
PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opJMP_far_a32(uint32_t fetchdat)
{
uint16_t seg;
uint32_t addr, old_pc;
addr = getlong();
seg = getword(); if (cpu_state.abrt) return 1;
old_pc = cpu_state.pc;
cpu_state.pc = addr;
loadcsjmp(seg, old_pc);
CPU_BLOCK_END();
PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opCALL_r16(uint32_t fetchdat)
{
int16_t addr = (int16_t)getwordf();
PUSH_W(cpu_state.pc);
cpu_state.pc += addr;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 3, -1, 0,0,1,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opCALL_r32(uint32_t fetchdat)
{
int32_t addr = getlong(); if (cpu_state.abrt) return 1;
PUSH_L(cpu_state.pc);
cpu_state.pc += addr;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 5, -1, 0,0,0,1, 0);
PREFETCH_FLUSH();
return 0;
}
static int opRET_w(uint32_t fetchdat)
{
uint16_t ret;
ret = POP_W(); if (cpu_state.abrt) return 1;
cpu_state.pc = ret;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 5 : 10);
PREFETCH_RUN(10, 1, -1, 1,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opRET_l(uint32_t fetchdat)
{
uint32_t ret;
ret = POP_L(); if (cpu_state.abrt) return 1;
cpu_state.pc = ret;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 5 : 10);
PREFETCH_RUN(10, 1, -1, 0,1,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opRET_w_imm(uint32_t fetchdat)
{
uint16_t ret;
uint16_t offset = getwordf();
ret = POP_W(); if (cpu_state.abrt) return 1;
if (stack32) ESP += offset;
else SP += offset;
cpu_state.pc = ret;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 5 : 10);
PREFETCH_RUN(10, 5, -1, 1,0,0,0, 0);
PREFETCH_FLUSH();
return 0;
}
static int opRET_l_imm(uint32_t fetchdat)
{
uint32_t ret;
uint16_t offset = getwordf();
ret = POP_L(); if (cpu_state.abrt) return 1;
if (stack32) ESP += offset;
else SP += offset;
cpu_state.pc = ret;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 5 : 10);
PREFETCH_RUN(10, 5, -1, 0,1,0,0, 0);
PREFETCH_FLUSH();
return 0;
}

View File

@@ -1,49 +0,0 @@
#define SSATB(val) (((val) < -128) ? -128 : (((val) > 127) ? 127 : (val)))
#define SSATW(val) (((val) < -32768) ? -32768 : (((val) > 32767) ? 32767 : (val)))
#define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val)))
#define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val)))
#define MMX_GETSRC() \
if (cpu_mod == 3) \
{ \
src = cpu_state.MM[cpu_rm]; \
CLOCK_CYCLES(1); \
} \
else \
{ \
SEG_CHECK_READ(cpu_state.ea_seg); \
src.q = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \
CLOCK_CYCLES(2); \
}
#define MMX_ENTER() \
if (!cpu_has_feature(CPU_FEATURE_MMX)) \
{ \
cpu_state.pc = cpu_state.oldpc; \
x86illegal(); \
return 1; \
} \
if (cr0 & 0xc) \
{ \
x86_int(7); \
return 1; \
} \
x87_set_mmx()
static int opEMMS(uint32_t fetchdat)
{
if (!cpu_has_feature(CPU_FEATURE_MMX))
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
if (cr0 & 4)
{
x86_int(7);
return 1;
}
x87_emms();
CLOCK_CYCLES(100); /*Guess*/
return 0;
}

View File

@@ -1,629 +0,0 @@
static int opPADDB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] += src.b[0];
cpu_state.MM[cpu_reg].b[1] += src.b[1];
cpu_state.MM[cpu_reg].b[2] += src.b[2];
cpu_state.MM[cpu_reg].b[3] += src.b[3];
cpu_state.MM[cpu_reg].b[4] += src.b[4];
cpu_state.MM[cpu_reg].b[5] += src.b[5];
cpu_state.MM[cpu_reg].b[6] += src.b[6];
cpu_state.MM[cpu_reg].b[7] += src.b[7];
return 0;
}
static int opPADDB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] += src.b[0];
cpu_state.MM[cpu_reg].b[1] += src.b[1];
cpu_state.MM[cpu_reg].b[2] += src.b[2];
cpu_state.MM[cpu_reg].b[3] += src.b[3];
cpu_state.MM[cpu_reg].b[4] += src.b[4];
cpu_state.MM[cpu_reg].b[5] += src.b[5];
cpu_state.MM[cpu_reg].b[6] += src.b[6];
cpu_state.MM[cpu_reg].b[7] += src.b[7];
return 0;
}
static int opPADDW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] += src.w[0];
cpu_state.MM[cpu_reg].w[1] += src.w[1];
cpu_state.MM[cpu_reg].w[2] += src.w[2];
cpu_state.MM[cpu_reg].w[3] += src.w[3];
return 0;
}
static int opPADDW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] += src.w[0];
cpu_state.MM[cpu_reg].w[1] += src.w[1];
cpu_state.MM[cpu_reg].w[2] += src.w[2];
cpu_state.MM[cpu_reg].w[3] += src.w[3];
return 0;
}
static int opPADDD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] += src.l[0];
cpu_state.MM[cpu_reg].l[1] += src.l[1];
return 0;
}
static int opPADDD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] += src.l[0];
cpu_state.MM[cpu_reg].l[1] += src.l[1];
return 0;
}
static int opPADDSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]);
return 0;
}
static int opPADDSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]);
return 0;
}
static int opPADDUSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]);
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]);
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]);
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]);
return 0;
}
static int opPADDUSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]);
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]);
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]);
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]);
return 0;
}
static int opPADDSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]);
return 0;
}
static int opPADDSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]);
return 0;
}
static int opPADDUSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]);
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]);
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]);
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]);
return 0;
}
static int opPADDUSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]);
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]);
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]);
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]);
return 0;
}
static int opPMADDWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
cpu_state.MM[cpu_reg].l[0] = 0x80000000;
else
cpu_state.MM[cpu_reg].sl[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]);
if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
cpu_state.MM[cpu_reg].l[1] = 0x80000000;
else
cpu_state.MM[cpu_reg].sl[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]);
return 0;
}
static int opPMADDWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
cpu_state.MM[cpu_reg].l[0] = 0x80000000;
else
cpu_state.MM[cpu_reg].sl[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]);
if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
cpu_state.MM[cpu_reg].l[1] = 0x80000000;
else
cpu_state.MM[cpu_reg].sl[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]);
return 0;
}
static int opPMULLW_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0];
cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1];
cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2];
cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3];
CLOCK_CYCLES(1);
}
else
{
MMX_REG src;
SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] *= src.w[0];
cpu_state.MM[cpu_reg].w[1] *= src.w[1];
cpu_state.MM[cpu_reg].w[2] *= src.w[2];
cpu_state.MM[cpu_reg].w[3] *= src.w[3];
CLOCK_CYCLES(2);
}
return 0;
}
static int opPMULLW_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0];
cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1];
cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2];
cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3];
CLOCK_CYCLES(1);
}
else
{
MMX_REG src;
SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] *= src.w[0];
cpu_state.MM[cpu_reg].w[1] *= src.w[1];
cpu_state.MM[cpu_reg].w[2] *= src.w[2];
cpu_state.MM[cpu_reg].w[3] *= src.w[3];
CLOCK_CYCLES(2);
}
return 0;
}
static int opPMULHW_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)cpu_state.MM[cpu_rm].sw[0]) >> 16;
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)cpu_state.MM[cpu_rm].sw[1]) >> 16;
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)cpu_state.MM[cpu_rm].sw[2]) >> 16;
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)cpu_state.MM[cpu_rm].sw[3]) >> 16;
CLOCK_CYCLES(1);
}
else
{
MMX_REG src;
SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16;
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) >> 16;
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) >> 16;
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) >> 16;
CLOCK_CYCLES(2);
}
return 0;
}
static int opPMULHW_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)cpu_state.MM[cpu_rm].sw[0]) >> 16;
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)cpu_state.MM[cpu_rm].sw[1]) >> 16;
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)cpu_state.MM[cpu_rm].sw[2]) >> 16;
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)cpu_state.MM[cpu_rm].sw[3]) >> 16;
CLOCK_CYCLES(1);
}
else
{
MMX_REG src;
SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16;
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) >> 16;
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) >> 16;
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) >> 16;
CLOCK_CYCLES(2);
}
return 0;
}
static int opPSUBB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] -= src.b[0];
cpu_state.MM[cpu_reg].b[1] -= src.b[1];
cpu_state.MM[cpu_reg].b[2] -= src.b[2];
cpu_state.MM[cpu_reg].b[3] -= src.b[3];
cpu_state.MM[cpu_reg].b[4] -= src.b[4];
cpu_state.MM[cpu_reg].b[5] -= src.b[5];
cpu_state.MM[cpu_reg].b[6] -= src.b[6];
cpu_state.MM[cpu_reg].b[7] -= src.b[7];
return 0;
}
static int opPSUBB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] -= src.b[0];
cpu_state.MM[cpu_reg].b[1] -= src.b[1];
cpu_state.MM[cpu_reg].b[2] -= src.b[2];
cpu_state.MM[cpu_reg].b[3] -= src.b[3];
cpu_state.MM[cpu_reg].b[4] -= src.b[4];
cpu_state.MM[cpu_reg].b[5] -= src.b[5];
cpu_state.MM[cpu_reg].b[6] -= src.b[6];
cpu_state.MM[cpu_reg].b[7] -= src.b[7];
return 0;
}
static int opPSUBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] -= src.w[0];
cpu_state.MM[cpu_reg].w[1] -= src.w[1];
cpu_state.MM[cpu_reg].w[2] -= src.w[2];
cpu_state.MM[cpu_reg].w[3] -= src.w[3];
return 0;
}
static int opPSUBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] -= src.w[0];
cpu_state.MM[cpu_reg].w[1] -= src.w[1];
cpu_state.MM[cpu_reg].w[2] -= src.w[2];
cpu_state.MM[cpu_reg].w[3] -= src.w[3];
return 0;
}
static int opPSUBD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] -= src.l[0];
cpu_state.MM[cpu_reg].l[1] -= src.l[1];
return 0;
}
static int opPSUBD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] -= src.l[0];
cpu_state.MM[cpu_reg].l[1] -= src.l[1];
return 0;
}
static int opPSUBSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]);
return 0;
}
static int opPSUBSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]);
return 0;
}
static int opPSUBUSB_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]);
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]);
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]);
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]);
return 0;
}
static int opPSUBUSB_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]);
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]);
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]);
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]);
return 0;
}
static int opPSUBSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]);
return 0;
}
static int opPSUBSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]);
return 0;
}
static int opPSUBUSW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]);
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]);
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]);
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]);
return 0;
}
static int opPSUBUSW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]);
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]);
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]);
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]);
return 0;
}

View File

@@ -1,169 +0,0 @@
static int opMOVD_l_mm_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l;
cpu_state.MM[cpu_reg].l[1] = 0;
CLOCK_CYCLES(1);
}
else
{
uint32_t dst;
SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].l[0] = dst;
cpu_state.MM[cpu_reg].l[1] = 0;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVD_l_mm_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l;
cpu_state.MM[cpu_reg].l[1] = 0;
CLOCK_CYCLES(1);
}
else
{
uint32_t dst;
SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].l[0] = dst;
cpu_state.MM[cpu_reg].l[1] = 0;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVD_mm_l_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
CLOCK_CYCLES(1);
}
else
{
SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVD_mm_l_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
CLOCK_CYCLES(1);
}
else
{
SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVQ_q_mm_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q;
CLOCK_CYCLES(1);
}
else
{
uint64_t dst;
SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].q = dst;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVQ_q_mm_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q;
CLOCK_CYCLES(1);
}
else
{
uint64_t dst;
SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].q = dst;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVQ_mm_q_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q;
CLOCK_CYCLES(1);
}
else
{
SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
return 0;
}
static int opMOVQ_mm_q_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q;
CLOCK_CYCLES(1);
}
else
{
SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
return 0;
}

View File

@@ -1,326 +0,0 @@
static int opPUNPCKLDQ_a16(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_16(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0];
CLOCK_CYCLES(1);
}
else
{
uint32_t src;
SEG_CHECK_READ(cpu_state.ea_seg);
src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].l[1] = src;
CLOCK_CYCLES(2);
}
return 0;
}
static int opPUNPCKLDQ_a32(uint32_t fetchdat)
{
MMX_ENTER();
fetch_ea_32(fetchdat);
if (cpu_mod == 3)
{
cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0];
CLOCK_CYCLES(1);
}
else
{
uint32_t src;
SEG_CHECK_READ(cpu_state.ea_seg);
src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].l[1] = src;
CLOCK_CYCLES(2);
}
return 0;
}
static int opPUNPCKHDQ_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1];
cpu_state.MM[cpu_reg].l[1] = src.l[1];
return 0;
}
static int opPUNPCKHDQ_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1];
cpu_state.MM[cpu_reg].l[1] = src.l[1];
return 0;
}
static int opPUNPCKLBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[7] = src.b[3];
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3];
cpu_state.MM[cpu_reg].b[5] = src.b[2];
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2];
cpu_state.MM[cpu_reg].b[3] = src.b[1];
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1];
cpu_state.MM[cpu_reg].b[1] = src.b[0];
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0];
return 0;
}
static int opPUNPCKLBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[7] = src.b[3];
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3];
cpu_state.MM[cpu_reg].b[5] = src.b[2];
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2];
cpu_state.MM[cpu_reg].b[3] = src.b[1];
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1];
cpu_state.MM[cpu_reg].b[1] = src.b[0];
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0];
return 0;
}
static int opPUNPCKHBW_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4];
cpu_state.MM[cpu_reg].b[1] = src.b[4];
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5];
cpu_state.MM[cpu_reg].b[3] = src.b[5];
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6];
cpu_state.MM[cpu_reg].b[5] = src.b[6];
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7];
cpu_state.MM[cpu_reg].b[7] = src.b[7];
return 0;
}
static int opPUNPCKHBW_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4];
cpu_state.MM[cpu_reg].b[1] = src.b[4];
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5];
cpu_state.MM[cpu_reg].b[3] = src.b[5];
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6];
cpu_state.MM[cpu_reg].b[5] = src.b[6];
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7];
cpu_state.MM[cpu_reg].b[7] = src.b[7];
return 0;
}
static int opPUNPCKLWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[3] = src.w[1];
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1];
cpu_state.MM[cpu_reg].w[1] = src.w[0];
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0];
return 0;
}
static int opPUNPCKLWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[3] = src.w[1];
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1];
cpu_state.MM[cpu_reg].w[1] = src.w[0];
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0];
return 0;
}
static int opPUNPCKHWD_a16(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2];
cpu_state.MM[cpu_reg].w[1] = src.w[2];
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3];
cpu_state.MM[cpu_reg].w[3] = src.w[3];
return 0;
}
static int opPUNPCKHWD_a32(uint32_t fetchdat)
{
MMX_REG src;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2];
cpu_state.MM[cpu_reg].w[1] = src.w[2];
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3];
cpu_state.MM[cpu_reg].w[3] = src.w[3];
return 0;
}
static int opPACKSSWB_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]);
return 0;
}
static int opPACKSSWB_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]);
cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]);
cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]);
cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]);
cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]);
cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]);
cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]);
cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]);
return 0;
}
static int opPACKUSWB_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]);
cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]);
cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]);
cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]);
return 0;
}
static int opPACKUSWB_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]);
cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]);
cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]);
cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]);
cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]);
cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]);
cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]);
cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]);
return 0;
}
static int opPACKSSDW_a16(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]);
return 0;
}
static int opPACKSSDW_a32(uint32_t fetchdat)
{
MMX_REG src, dst;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSRC();
dst = cpu_state.MM[cpu_reg];
cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]);
cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]);
cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]);
cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]);
return 0;
}

View File

@@ -1,453 +0,0 @@
#define MMX_GETSHIFT() \
if (cpu_mod == 3) \
{ \
shift = cpu_state.MM[cpu_rm].b[0]; \
CLOCK_CYCLES(1); \
} \
else \
{ \
SEG_CHECK_READ(cpu_state.ea_seg); \
shift = readmemb(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; \
CLOCK_CYCLES(2); \
}
static int opPSxxW_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
cpu_state.pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLW*/
if (shift > 15)
cpu_state.MM[reg].q = 0;
else
{
cpu_state.MM[reg].w[0] >>= shift;
cpu_state.MM[reg].w[1] >>= shift;
cpu_state.MM[reg].w[2] >>= shift;
cpu_state.MM[reg].w[3] >>= shift;
}
break;
case 0x20: /*PSRAW*/
if (shift > 15)
shift = 15;
cpu_state.MM[reg].sw[0] >>= shift;
cpu_state.MM[reg].sw[1] >>= shift;
cpu_state.MM[reg].sw[2] >>= shift;
cpu_state.MM[reg].sw[3] >>= shift;
break;
case 0x30: /*PSLLW*/
if (shift > 15)
cpu_state.MM[reg].q = 0;
else
{
cpu_state.MM[reg].w[0] <<= shift;
cpu_state.MM[reg].w[1] <<= shift;
cpu_state.MM[reg].w[2] <<= shift;
cpu_state.MM[reg].w[3] <<= shift;
}
break;
default:
x386_dynarec_log("Bad PSxxW (0F 71) instruction %02X\n", op);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
}
CLOCK_CYCLES(1);
return 0;
}
static int opPSLLW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].w[0] <<= shift;
cpu_state.MM[cpu_reg].w[1] <<= shift;
cpu_state.MM[cpu_reg].w[2] <<= shift;
cpu_state.MM[cpu_reg].w[3] <<= shift;
}
return 0;
}
static int opPSLLW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].w[0] <<= shift;
cpu_state.MM[cpu_reg].w[1] <<= shift;
cpu_state.MM[cpu_reg].w[2] <<= shift;
cpu_state.MM[cpu_reg].w[3] <<= shift;
}
return 0;
}
static int opPSRLW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].w[0] >>= shift;
cpu_state.MM[cpu_reg].w[1] >>= shift;
cpu_state.MM[cpu_reg].w[2] >>= shift;
cpu_state.MM[cpu_reg].w[3] >>= shift;
}
return 0;
}
static int opPSRLW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].w[0] >>= shift;
cpu_state.MM[cpu_reg].w[1] >>= shift;
cpu_state.MM[cpu_reg].w[2] >>= shift;
cpu_state.MM[cpu_reg].w[3] >>= shift;
}
return 0;
}
static int opPSRAW_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
shift = 15;
cpu_state.MM[cpu_reg].sw[0] >>= shift;
cpu_state.MM[cpu_reg].sw[1] >>= shift;
cpu_state.MM[cpu_reg].sw[2] >>= shift;
cpu_state.MM[cpu_reg].sw[3] >>= shift;
return 0;
}
static int opPSRAW_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 15)
shift = 15;
cpu_state.MM[cpu_reg].sw[0] >>= shift;
cpu_state.MM[cpu_reg].sw[1] >>= shift;
cpu_state.MM[cpu_reg].sw[2] >>= shift;
cpu_state.MM[cpu_reg].sw[3] >>= shift;
return 0;
}
static int opPSxxD_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
cpu_state.pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLD*/
if (shift > 31)
cpu_state.MM[reg].q = 0;
else
{
cpu_state.MM[reg].l[0] >>= shift;
cpu_state.MM[reg].l[1] >>= shift;
}
break;
case 0x20: /*PSRAD*/
if (shift > 31)
shift = 31;
cpu_state.MM[reg].sl[0] >>= shift;
cpu_state.MM[reg].sl[1] >>= shift;
break;
case 0x30: /*PSLLD*/
if (shift > 31)
cpu_state.MM[reg].q = 0;
else
{
cpu_state.MM[reg].l[0] <<= shift;
cpu_state.MM[reg].l[1] <<= shift;
}
break;
default:
x386_dynarec_log("Bad PSxxD (0F 72) instruction %02X\n", op);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
}
CLOCK_CYCLES(1);
return 0;
}
static int opPSLLD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].l[0] <<= shift;
cpu_state.MM[cpu_reg].l[1] <<= shift;
}
return 0;
}
static int opPSLLD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].l[0] <<= shift;
cpu_state.MM[cpu_reg].l[1] <<= shift;
}
return 0;
}
static int opPSRLD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].l[0] >>= shift;
cpu_state.MM[cpu_reg].l[1] >>= shift;
}
return 0;
}
static int opPSRLD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
cpu_state.MM[cpu_reg].q = 0;
else
{
cpu_state.MM[cpu_reg].l[0] >>= shift;
cpu_state.MM[cpu_reg].l[1] >>= shift;
}
return 0;
}
static int opPSRAD_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
shift = 31;
cpu_state.MM[cpu_reg].sl[0] >>= shift;
cpu_state.MM[cpu_reg].sl[1] >>= shift;
return 0;
}
static int opPSRAD_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 31)
shift = 31;
cpu_state.MM[cpu_reg].sl[0] >>= shift;
cpu_state.MM[cpu_reg].sl[1] >>= shift;
return 0;
}
static int opPSxxQ_imm(uint32_t fetchdat)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = (fetchdat >> 8) & 0xff;
cpu_state.pc += 2;
MMX_ENTER();
switch (op)
{
case 0x10: /*PSRLW*/
if (shift > 63)
cpu_state.MM[reg].q = 0;
else
cpu_state.MM[reg].q >>= shift;
break;
case 0x20: /*PSRAW*/
if (shift > 63)
shift = 63;
cpu_state.MM[reg].sq >>= shift;
break;
case 0x30: /*PSLLW*/
if (shift > 63)
cpu_state.MM[reg].q = 0;
else
cpu_state.MM[reg].q <<= shift;
break;
default:
x386_dynarec_log("Bad PSxxQ (0F 73) instruction %02X\n", op);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 0;
}
CLOCK_CYCLES(1);
return 0;
}
static int opPSLLQ_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
cpu_state.MM[cpu_reg].q = 0;
else
cpu_state.MM[cpu_reg].q <<= shift;
return 0;
}
static int opPSLLQ_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
cpu_state.MM[cpu_reg].q = 0;
else
cpu_state.MM[cpu_reg].q <<= shift;
return 0;
}
static int opPSRLQ_a16(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_16(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
cpu_state.MM[cpu_reg].q = 0;
else
cpu_state.MM[cpu_reg].q >>= shift;
return 0;
}
static int opPSRLQ_a32(uint32_t fetchdat)
{
int shift;
MMX_ENTER();
fetch_ea_32(fetchdat);
MMX_GETSHIFT();
if (shift > 63)
cpu_state.MM[cpu_reg].q = 0;
else
cpu_state.MM[cpu_reg].q >>= shift;
return 0;
}

View File

@@ -1,306 +0,0 @@
static int opMOV_r_CRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from CRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg)
{
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4))
{
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
x386_dynarec_log("Bad read of CR%i %i\n",rmdat&7,cpu_reg);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_r_CRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from CRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg)
{
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4))
{
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
x386_dynarec_log("Bad read of CR%i %i\n",rmdat&7,cpu_reg);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
return 0;
}
static int opMOV_r_DRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from DRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_r_DRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from DRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
return 0;
}
static int opMOV_CRx_r_a16(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load CRx\n");
x86gpf(NULL,0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg)
{
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm=4;
if (is486 && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else if (isibmcpu)
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (is486 && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4))
{
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
x386_dynarec_log("Bad load CR%i\n", cpu_reg);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_CRx_r_a32(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load CRx\n");
x86gpf(NULL,0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg)
{
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm=4;
if (is486 && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (is486 && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4))
{
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
x386_dynarec_log("Bad load CR%i\n", cpu_reg);
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 1);
return 0;
}
static int opMOV_DRx_r_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load DRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_DRx_r_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load DRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
return 0;
}
static int opMOV_r_TRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from TRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
cpu_state.regs[cpu_rm].l = 0;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_r_TRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load from TRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
cpu_state.regs[cpu_rm].l = 0;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
return 0;
}
static int opMOV_TRx_r_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load TRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
return 0;
}
static int opMOV_TRx_r_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x386_dynarec_log("Can't load TRx\n");
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
return 0;
}

View File

@@ -1,474 +0,0 @@
static int opARPL_a16(uint32_t fetchdat)
{
uint16_t temp_seg;
NOTRM
fetch_ea_16(fetchdat);
/* x386_dynarec_log("ARPL_a16\n"); */
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3))
{
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
seteaw(temp_seg); if (cpu_state.abrt) return 1;
cpu_state.flags |= Z_FLAG;
}
else
cpu_state.flags &= ~Z_FLAG;
CLOCK_CYCLES(is486 ? 9 : 20);
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0);
return 0;
}
static int opARPL_a32(uint32_t fetchdat)
{
uint16_t temp_seg;
NOTRM
fetch_ea_32(fetchdat);
/* x386_dynarec_log("ARPL_a32\n"); */
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3))
{
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
seteaw(temp_seg); if (cpu_state.abrt) return 1;
cpu_state.flags |= Z_FLAG;
}
else
cpu_state.flags &= ~Z_FLAG;
CLOCK_CYCLES(is486 ? 9 : 20);
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1);
return 0;
}
#define opLAR(name, fetch_ea, is32, ea32) \
static int opLAR_ ## name(uint32_t fetchdat) \
{ \
int valid; \
uint16_t sel, desc = 0; \
\
NOTRM \
fetch_ea(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
\
sel = geteaw(); if (cpu_state.abrt) return 1; \
\
flags_rebuild(); \
if (!(sel & 0xfffc)) { cpu_state.flags &= ~Z_FLAG; return 0; } /*Null selector*/ \
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
if (valid) \
{ \
cpl_override = 1; \
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \
cpl_override = 0; if (cpu_state.abrt) return 1; \
} \
cpu_state.flags &= ~Z_FLAG; \
if ((desc & 0x1f00) == 0x000) valid = 0; \
if ((desc & 0x1f00) == 0x800) valid = 0; \
if ((desc & 0x1f00) == 0xa00) valid = 0; \
if ((desc & 0x1f00) == 0xd00) valid = 0; \
if ((desc & 0x1c00) < 0x1c00) /*Exclude conforming code segments*/ \
{ \
int dpl = (desc >> 13) & 3; \
if (dpl < CPL || dpl < (sel & 3)) valid = 0; \
} \
if (valid) \
{ \
cpu_state.flags |= Z_FLAG; \
cpl_override = 1; \
if (is32) \
cpu_state.regs[cpu_reg].l = readmeml(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xffff00; \
else \
cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xff00; \
cpl_override = 0; \
} \
CLOCK_CYCLES(11); \
PREFETCH_RUN(11, 2, rmdat, 2,0,0,0, ea32); \
return cpu_state.abrt; \
}
opLAR(w_a16, fetch_ea_16, 0, 0)
opLAR(w_a32, fetch_ea_32, 0, 1)
opLAR(l_a16, fetch_ea_16, 1, 0)
opLAR(l_a32, fetch_ea_32, 1, 1)
#define opLSL(name, fetch_ea, is32, ea32) \
static int opLSL_ ## name(uint32_t fetchdat) \
{ \
int valid; \
uint16_t sel, desc = 0; \
\
NOTRM \
fetch_ea(fetchdat); \
if (cpu_mod != 3) \
SEG_CHECK_READ(cpu_state.ea_seg); \
\
sel = geteaw(); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
cpu_state.flags &= ~Z_FLAG; \
if (!(sel & 0xfffc)) return 0; /*Null selector*/ \
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
if (valid) \
{ \
cpl_override = 1; \
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \
cpl_override = 0; if (cpu_state.abrt) return 1; \
} \
if ((desc & 0x1400) == 0x400) valid = 0; /*Interrupt or trap or call gate*/ \
if ((desc & 0x1f00) == 0x000) valid = 0; /*Invalid*/ \
if ((desc & 0x1f00) == 0xa00) valid = 0; /*Invalid*/ \
if ((desc & 0x1c00) != 0x1c00) /*Exclude conforming code segments*/ \
{ \
int rpl = (desc >> 13) & 3; \
if (rpl < CPL || rpl < (sel & 3)) valid = 0; \
} \
if (valid) \
{ \
cpu_state.flags |= Z_FLAG; \
cpl_override = 1; \
if (is32) \
{ \
cpu_state.regs[cpu_reg].l = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \
cpu_state.regs[cpu_reg].l |= (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0xF) << 16; \
if (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0x80) \
{ \
cpu_state.regs[cpu_reg].l <<= 12; \
cpu_state.regs[cpu_reg].l |= 0xFFF; \
} \
} \
else \
cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \
cpl_override = 0; \
} \
CLOCK_CYCLES(10); \
PREFETCH_RUN(10, 2, rmdat, 4,0,0,0, ea32); \
return cpu_state.abrt; \
}
opLSL(w_a16, fetch_ea_16, 0, 0)
opLSL(w_a32, fetch_ea_32, 0, 1)
opLSL(l_a16, fetch_ea_16, 1, 0)
opLSL(l_a32, fetch_ea_32, 1, 1)
static int op0F00_common(uint32_t fetchdat, int ea32)
{
int dpl, valid, granularity;
uint32_t addr, base, limit;
uint16_t desc, sel;
uint8_t access;
/* x386_dynarec_log("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */
switch (rmdat & 0x38)
{
case 0x00: /*SLDT*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(ldt.seg);
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x08: /*STR*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(tr.seg);
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x10: /*LLDT*/
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
x386_dynarec_log("Invalid LLDT!\n");
x86gpf(NULL,0);
return 1;
}
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
addr = (sel & ~7) + gdt.base;
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
access = readmemb(0, addr + 5);
granularity = readmemb(0, addr + 6) & 0x80;
if (cpu_state.abrt) return 1;
ldt.limit = limit;
ldt.access = access;
if (granularity)
{
ldt.limit <<= 12;
ldt.limit |= 0xfff;
}
ldt.base = base;
ldt.seg = sel;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32);
break;
case 0x18: /*LTR*/
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
x386_dynarec_log("Invalid LTR!\n");
x86gpf(NULL,0);
break;
}
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
addr = (sel & ~7) + gdt.base;
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
access = readmemb(0, addr + 5);
granularity = readmemb(0, addr + 6) & 0x80;
if (cpu_state.abrt) return 1;
access |= 2;
writememb(0, addr + 5, access);
if (cpu_state.abrt) return 1;
tr.seg = sel;
tr.limit = limit;
tr.access = access;
if (granularity)
{
tr.limit <<= 12;
tr.limit |= 0xFFF;
}
tr.base = base;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32);
break;
case 0x20: /*VERR*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
cpu_state.flags &= ~Z_FLAG;
if (!(sel & 0xfffc)) return 0; /*Null selector*/
cpl_override = 1;
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4);
cpl_override = 0; if (cpu_state.abrt) return 1;
if (!(desc & 0x1000)) valid = 0;
if ((desc & 0xC00) != 0xC00) /*Exclude conforming code segments*/
{
dpl = (desc >> 13) & 3; /*Check permissions*/
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
}
if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/
if (valid) cpu_state.flags |= Z_FLAG;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32);
break;
case 0x28: /*VERW*/
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
cpu_state.flags &= ~Z_FLAG;
if (!(sel & 0xfffc)) return 0; /*Null selector*/
cpl_override = 1;
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4);
cpl_override = 0; if (cpu_state.abrt) return 1;
if (!(desc & 0x1000)) valid = 0;
dpl = (desc >> 13) & 3; /*Check permissions*/
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
if (desc & 0x0800) valid = 0; /*Code*/
if (!(desc & 0x0200)) valid = 0; /*Read-only data*/
if (valid) cpu_state.flags |= Z_FLAG;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32);
break;
default:
x386_dynarec_log("Bad 0F 00 opcode %02X\n", rmdat & 0x38);
cpu_state.pc -= 3;
x86illegal();
break;
}
return cpu_state.abrt;
}
static int op0F00_a16(uint32_t fetchdat)
{
NOTRM
fetch_ea_16(fetchdat);
return op0F00_common(fetchdat, 0);
}
static int op0F00_a32(uint32_t fetchdat)
{
NOTRM
fetch_ea_32(fetchdat);
return op0F00_common(fetchdat, 1);
}
static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32)
{
uint32_t base;
uint16_t limit, tempw;
/* x386_dynarec_log("op0F01 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); */
switch (rmdat & 0x38)
{
case 0x00: /*SGDT*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(gdt.limit);
base = gdt.base; /* is32 ? gdt.base : (gdt.base & 0xffffff); */
if (is286)
base |= 0xff000000;
writememl(easeg, cpu_state.eaaddr + 2, base);
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32);
break;
case 0x08: /*SIDT*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(idt.limit);
base = idt.base;
if (is286)
base |= 0xff000000;
writememl(easeg, cpu_state.eaaddr + 2, base);
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32);
break;
case 0x10: /*LGDT*/
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
x386_dynarec_log("Invalid LGDT!\n");
x86gpf(NULL,0);
break;
}
/* x386_dynarec_log("LGDT %08X:%08X\n", easeg, eaaddr); */
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
limit = geteaw();
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
/* x386_dynarec_log(" %08X %04X\n", base, limit); */
gdt.limit = limit;
gdt.base = base;
if (!is32) gdt.base &= 0xffffff;
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32);
break;
case 0x18: /*LIDT*/
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
x386_dynarec_log("Invalid LIDT!\n");
x86gpf(NULL,0);
break;
}
/* x386_dynarec_log("LIDT %08X:%08X\n", easeg, eaaddr); */
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
limit = geteaw();
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
/* x386_dynarec_log(" %08X %04X\n", base, limit); */
idt.limit = limit;
idt.base = base;
if (!is32) idt.base &= 0xffffff;
CLOCK_CYCLES(11);
PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32);
break;
case 0x20: /*SMSW*/
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (is486) seteaw(msw);
else if (is386) seteaw(msw | 0xFF00);
else seteaw(msw | 0xFFF0);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x30: /*LMSW*/
if ((CPL || cpu_state.eflags&VM_FLAG) && (msw&1))
{
x386_dynarec_log("LMSW - ring not zero!\n");
x86gpf(NULL, 0);
break;
}
if (cpu_mod != 3)
SEG_CHECK_READ(cpu_state.ea_seg);
tempw = geteaw(); if (cpu_state.abrt) return 1;
if (msw & 1) tempw |= 1;
if (is386)
{
tempw &= ~0x10;
tempw |= (msw & 0x10);
}
else tempw &= 0xF;
msw = tempw;
if (msw & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x38: /*INVLPG*/
if (is486)
{
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
x386_dynarec_log("Invalid INVLPG!\n");
x86gpf(NULL, 0);
break;
}
SEG_CHECK_READ(cpu_state.ea_seg);
mmu_invalidate(ds + cpu_state.eaaddr);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, rmdat, 0,0,0,0, ea32);
break;
}
default:
x386_dynarec_log("Bad 0F 01 opcode %02X\n", rmdat & 0x38);
cpu_state.pc -= 3;
x86illegal();
break;
}
return cpu_state.abrt;
}
static int op0F01_w_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
return op0F01_common(fetchdat, 0, 0, 0);
}
static int op0F01_w_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
return op0F01_common(fetchdat, 0, 0, 1);
}
static int op0F01_l_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
return op0F01_common(fetchdat, 1, 0, 0);
}
static int op0F01_l_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
return op0F01_common(fetchdat, 1, 0, 1);
}
static int op0F01_286(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
return op0F01_common(fetchdat, 0, 1, 0);
}

View File

@@ -1,525 +0,0 @@
#define PUSH_W_OP(reg) \
static int opPUSH_ ## reg (uint32_t fetchdat) \
{ \
PUSH_W(reg); \
CLOCK_CYCLES((is486) ? 1 : 2); \
PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \
return cpu_state.abrt; \
}
#define PUSH_L_OP(reg) \
static int opPUSH_ ## reg (uint32_t fetchdat) \
{ \
PUSH_L(reg); \
CLOCK_CYCLES((is486) ? 1 : 2); \
PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \
return cpu_state.abrt; \
}
#define POP_W_OP(reg) \
static int opPOP_ ## reg (uint32_t fetchdat) \
{ \
reg = POP_W(); \
CLOCK_CYCLES((is486) ? 1 : 4); \
PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); \
return cpu_state.abrt; \
}
#define POP_L_OP(reg) \
static int opPOP_ ## reg (uint32_t fetchdat) \
{ \
reg = POP_L(); \
CLOCK_CYCLES((is486) ? 1 : 4); \
PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); \
return cpu_state.abrt; \
}
PUSH_W_OP(AX)
PUSH_W_OP(BX)
PUSH_W_OP(CX)
PUSH_W_OP(DX)
PUSH_W_OP(SI)
PUSH_W_OP(DI)
PUSH_W_OP(BP)
PUSH_W_OP(SP)
PUSH_L_OP(EAX)
PUSH_L_OP(EBX)
PUSH_L_OP(ECX)
PUSH_L_OP(EDX)
PUSH_L_OP(ESI)
PUSH_L_OP(EDI)
PUSH_L_OP(EBP)
PUSH_L_OP(ESP)
POP_W_OP(AX)
POP_W_OP(BX)
POP_W_OP(CX)
POP_W_OP(DX)
POP_W_OP(SI)
POP_W_OP(DI)
POP_W_OP(BP)
POP_W_OP(SP)
POP_L_OP(EAX)
POP_L_OP(EBX)
POP_L_OP(ECX)
POP_L_OP(EDX)
POP_L_OP(ESI)
POP_L_OP(EDI)
POP_L_OP(EBP)
POP_L_OP(ESP)
static int opPUSHA_w(uint32_t fetchdat)
{
if (stack32)
{
writememw(ss, ESP - 2, AX);
writememw(ss, ESP - 4, CX);
writememw(ss, ESP - 6, DX);
writememw(ss, ESP - 8, BX);
writememw(ss, ESP - 10, SP);
writememw(ss, ESP - 12, BP);
writememw(ss, ESP - 14, SI);
writememw(ss, ESP - 16, DI);
if (!cpu_state.abrt) ESP -= 16;
}
else
{
writememw(ss, ((SP - 2) & 0xFFFF), AX);
writememw(ss, ((SP - 4) & 0xFFFF), CX);
writememw(ss, ((SP - 6) & 0xFFFF), DX);
writememw(ss, ((SP - 8) & 0xFFFF), BX);
writememw(ss, ((SP - 10) & 0xFFFF), SP);
writememw(ss, ((SP - 12) & 0xFFFF), BP);
writememw(ss, ((SP - 14) & 0xFFFF), SI);
writememw(ss, ((SP - 16) & 0xFFFF), DI);
if (!cpu_state.abrt) SP -= 16;
}
CLOCK_CYCLES((is486) ? 11 : 18);
PREFETCH_RUN(18, 1, -1, 0,0,8,0, 0);
return cpu_state.abrt;
}
static int opPUSHA_l(uint32_t fetchdat)
{
if (stack32)
{
writememl(ss, ESP - 4, EAX);
writememl(ss, ESP - 8, ECX);
writememl(ss, ESP - 12, EDX);
writememl(ss, ESP - 16, EBX);
writememl(ss, ESP - 20, ESP);
writememl(ss, ESP - 24, EBP);
writememl(ss, ESP - 28, ESI);
writememl(ss, ESP - 32, EDI);
if (!cpu_state.abrt) ESP -= 32;
}
else
{
writememl(ss, ((SP - 4) & 0xFFFF), EAX);
writememl(ss, ((SP - 8) & 0xFFFF), ECX);
writememl(ss, ((SP - 12) & 0xFFFF), EDX);
writememl(ss, ((SP - 16) & 0xFFFF), EBX);
writememl(ss, ((SP - 20) & 0xFFFF), ESP);
writememl(ss, ((SP - 24) & 0xFFFF), EBP);
writememl(ss, ((SP - 28) & 0xFFFF), ESI);
writememl(ss, ((SP - 32) & 0xFFFF), EDI);
if (!cpu_state.abrt) SP -= 32;
}
CLOCK_CYCLES((is486) ? 11 : 18);
PREFETCH_RUN(18, 1, -1, 0,0,0,8, 0);
return cpu_state.abrt;
}
static int opPOPA_w(uint32_t fetchdat)
{
if (stack32)
{
DI = readmemw(ss, ESP); if (cpu_state.abrt) return 1;
SI = readmemw(ss, ESP + 2); if (cpu_state.abrt) return 1;
BP = readmemw(ss, ESP + 4); if (cpu_state.abrt) return 1;
BX = readmemw(ss, ESP + 8); if (cpu_state.abrt) return 1;
DX = readmemw(ss, ESP + 10); if (cpu_state.abrt) return 1;
CX = readmemw(ss, ESP + 12); if (cpu_state.abrt) return 1;
AX = readmemw(ss, ESP + 14); if (cpu_state.abrt) return 1;
ESP += 16;
}
else
{
DI = readmemw(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1;
SI = readmemw(ss, ((SP + 2) & 0xFFFF)); if (cpu_state.abrt) return 1;
BP = readmemw(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1;
BX = readmemw(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1;
DX = readmemw(ss, ((SP + 10) & 0xFFFF)); if (cpu_state.abrt) return 1;
CX = readmemw(ss, ((SP + 12) & 0xFFFF)); if (cpu_state.abrt) return 1;
AX = readmemw(ss, ((SP + 14) & 0xFFFF)); if (cpu_state.abrt) return 1;
SP += 16;
}
CLOCK_CYCLES((is486) ? 9 : 24);
PREFETCH_RUN(24, 1, -1, 7,0,0,0, 0);
return 0;
}
static int opPOPA_l(uint32_t fetchdat)
{
if (stack32)
{
EDI = readmeml(ss, ESP); if (cpu_state.abrt) return 1;
ESI = readmeml(ss, ESP + 4); if (cpu_state.abrt) return 1;
EBP = readmeml(ss, ESP + 8); if (cpu_state.abrt) return 1;
EBX = readmeml(ss, ESP + 16); if (cpu_state.abrt) return 1;
EDX = readmeml(ss, ESP + 20); if (cpu_state.abrt) return 1;
ECX = readmeml(ss, ESP + 24); if (cpu_state.abrt) return 1;
EAX = readmeml(ss, ESP + 28); if (cpu_state.abrt) return 1;
ESP += 32;
}
else
{
EDI = readmeml(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1;
ESI = readmeml(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1;
EBP = readmeml(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1;
EBX = readmeml(ss, ((SP + 16) & 0xFFFF)); if (cpu_state.abrt) return 1;
EDX = readmeml(ss, ((SP + 20) & 0xFFFF)); if (cpu_state.abrt) return 1;
ECX = readmeml(ss, ((SP + 24) & 0xFFFF)); if (cpu_state.abrt) return 1;
EAX = readmeml(ss, ((SP + 28) & 0xFFFF)); if (cpu_state.abrt) return 1;
SP += 32;
}
CLOCK_CYCLES((is486) ? 9 : 24);
PREFETCH_RUN(24, 1, -1, 0,7,0,0, 0);
return 0;
}
static int opPUSH_imm_w(uint32_t fetchdat)
{
uint16_t val = getwordf();
PUSH_W(val);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
return cpu_state.abrt;
}
static int opPUSH_imm_l(uint32_t fetchdat)
{
uint32_t val = getlong(); if (cpu_state.abrt) return 1;
PUSH_L(val);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0);
return cpu_state.abrt;
}
static int opPUSH_imm_bw(uint32_t fetchdat)
{
uint16_t tempw = getbytef();
if (tempw & 0x80) tempw |= 0xFF00;
PUSH_W(tempw);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 2, -1, 0,0,1,0, 0);
return cpu_state.abrt;
}
static int opPUSH_imm_bl(uint32_t fetchdat)
{
uint32_t templ = getbytef();
if (templ & 0x80) templ |= 0xFFFFFF00;
PUSH_L(templ);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 2, -1, 0,0,0,1, 0);
return cpu_state.abrt;
}
static int opPOPW_a16(uint32_t fetchdat)
{
uint16_t temp;
temp = POP_W(); if (cpu_state.abrt) return 1;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(temp);
if (cpu_state.abrt)
{
if (stack32) ESP -= 2;
else SP -= 2;
}
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 0);
return cpu_state.abrt;
}
static int opPOPW_a32(uint32_t fetchdat)
{
uint16_t temp;
temp = POP_W(); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(temp);
if (cpu_state.abrt)
{
if (stack32) ESP -= 2;
else SP -= 2;
}
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 1);
return cpu_state.abrt;
}
static int opPOPL_a16(uint32_t fetchdat)
{
uint32_t temp;
temp = POP_L(); if (cpu_state.abrt) return 1;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(temp);
if (cpu_state.abrt)
{
if (stack32) ESP -= 4;
else SP -= 4;
}
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 0);
return cpu_state.abrt;
}
static int opPOPL_a32(uint32_t fetchdat)
{
uint32_t temp;
temp = POP_L(); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(temp);
if (cpu_state.abrt)
{
if (stack32) ESP -= 4;
else SP -= 4;
}
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 1);
return cpu_state.abrt;
}
static int opENTER_w(uint32_t fetchdat)
{
uint16_t offset;
int count;
uint32_t tempEBP, tempESP, frame_ptr;
int reads = 0, writes = 1, instr_cycles = 0;
uint16_t tempw;
offset = getwordf();
count = (fetchdat >> 16) & 0xff; cpu_state.pc++;
tempEBP = EBP;
tempESP = ESP;
PUSH_W(BP); if (cpu_state.abrt) return 1;
frame_ptr = ESP;
if (count > 0)
{
while (--count)
{
BP -= 2;
tempw = readmemw(ss, BP);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
PUSH_W(tempw);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
CLOCK_CYCLES((is486) ? 3 : 4);
reads++; writes++; instr_cycles += (is486) ? 3 : 4;
}
PUSH_W(frame_ptr);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
CLOCK_CYCLES((is486) ? 3 : 5);
writes++; instr_cycles += (is486) ? 3 : 5;
}
BP = frame_ptr;
if (stack32) ESP -= offset;
else SP -= offset;
CLOCK_CYCLES((is486) ? 14 : 10);
instr_cycles += (is486) ? 14 : 10;
PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0);
return 0;
}
static int opENTER_l(uint32_t fetchdat)
{
uint16_t offset;
int count;
uint32_t tempEBP, tempESP, frame_ptr;
int reads = 0, writes = 1, instr_cycles = 0;
uint32_t templ;
offset = getwordf();
count = (fetchdat >> 16) & 0xff; cpu_state.pc++;
tempEBP = EBP; tempESP = ESP;
PUSH_L(EBP); if (cpu_state.abrt) return 1;
frame_ptr = ESP;
if (count > 0)
{
while (--count)
{
EBP -= 4;
templ = readmeml(ss, EBP);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
PUSH_L(templ);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
CLOCK_CYCLES((is486) ? 3 : 4);
reads++; writes++; instr_cycles += (is486) ? 3 : 4;
}
PUSH_L(frame_ptr);
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
CLOCK_CYCLES((is486) ? 3 : 5);
writes++; instr_cycles += (is486) ? 3 : 5;
}
EBP = frame_ptr;
if (stack32) ESP -= offset;
else SP -= offset;
CLOCK_CYCLES((is486) ? 14 : 10);
instr_cycles += (is486) ? 14 : 10;
PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0);
return 0;
}
static int opLEAVE_w(uint32_t fetchdat)
{
uint32_t tempESP = ESP;
uint16_t temp;
SP = BP;
temp = POP_W();
if (cpu_state.abrt) { ESP = tempESP; return 1; }
BP = temp;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opLEAVE_l(uint32_t fetchdat)
{
uint32_t tempESP = ESP;
uint32_t temp;
ESP = EBP;
temp = POP_L();
if (cpu_state.abrt) { ESP = tempESP; return 1; }
EBP = temp;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0);
return 0;
}
#define PUSH_SEG_OPS(seg) \
static int opPUSH_ ## seg ## _w(uint32_t fetchdat) \
{ \
PUSH_W(seg); \
CLOCK_CYCLES(2); \
PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \
return cpu_state.abrt; \
} \
static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \
{ \
PUSH_L(seg); \
CLOCK_CYCLES(2); \
PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \
return cpu_state.abrt; \
}
#define POP_SEG_OPS(seg, realseg) \
static int opPOP_ ## seg ## _w(uint32_t fetchdat) \
{ \
uint16_t temp_seg; \
uint32_t temp_esp = ESP; \
temp_seg = POP_W(); if (cpu_state.abrt) return 1; \
loadseg(temp_seg, realseg); if (cpu_state.abrt) ESP = temp_esp; \
CLOCK_CYCLES(is486 ? 3 : 7); \
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \
return cpu_state.abrt; \
} \
static int opPOP_ ## seg ## _l(uint32_t fetchdat) \
{ \
uint32_t temp_seg; \
uint32_t temp_esp = ESP; \
temp_seg = POP_L(); if (cpu_state.abrt) return 1; \
loadseg(temp_seg & 0xffff, realseg); if (cpu_state.abrt) ESP = temp_esp; \
CLOCK_CYCLES(is486 ? 3 : 7); \
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \
return cpu_state.abrt; \
}
PUSH_SEG_OPS(CS)
PUSH_SEG_OPS(DS)
PUSH_SEG_OPS(ES)
PUSH_SEG_OPS(FS)
PUSH_SEG_OPS(GS)
PUSH_SEG_OPS(SS)
POP_SEG_OPS(DS, &cpu_state.seg_ds)
POP_SEG_OPS(ES, &cpu_state.seg_es)
POP_SEG_OPS(FS, &cpu_state.seg_fs)
POP_SEG_OPS(GS, &cpu_state.seg_gs)
static int opPOP_SS_w(uint32_t fetchdat)
{
uint16_t temp_seg;
uint32_t temp_esp = ESP;
temp_seg = POP_W(); if (cpu_state.abrt) return 1;
loadseg(temp_seg, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
CLOCK_CYCLES(is486 ? 3 : 7);
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0);
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return 1;
}
static int opPOP_SS_l(uint32_t fetchdat)
{
uint32_t temp_seg;
uint32_t temp_esp = ESP;
temp_seg = POP_L(); if (cpu_state.abrt) return 1;
loadseg(temp_seg & 0xffff, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
CLOCK_CYCLES(is486 ? 3 : 7);
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0);
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return 1;
}

View File

@@ -1,597 +0,0 @@
static int opMOVSB_a16(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememb(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { DI--; SI--; }
else { DI++; SI++; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opMOVSB_a32(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememb(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { EDI--; ESI--; }
else { EDI++; ESI++; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opMOVSW_a16(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememw(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
else { DI += 2; SI += 2; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opMOVSW_a32(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememw(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; }
else { EDI += 2; ESI += 2; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opMOVSL_a16(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememl(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; }
else { DI += 4; SI += 4; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,1, 0);
return 0;
}
static int opMOVSL_a32(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_WRITE(&cpu_state.seg_es);
temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememl(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; }
else { EDI += 4; ESI += 4; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,1, 1);
return 0;
}
static int opCMPSB_a16(uint32_t fetchdat)
{
uint8_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmemb(cpu_state.ea_seg->base, SI);
dst = readmemb(es, DI); if (cpu_state.abrt) return 1;
setsub8(src, dst);
if (cpu_state.flags & D_FLAG) { DI--; SI--; }
else { DI++; SI++; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0);
return 0;
}
static int opCMPSB_a32(uint32_t fetchdat)
{
uint8_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmemb(cpu_state.ea_seg->base, ESI);
dst = readmemb(es, EDI); if (cpu_state.abrt) return 1;
setsub8(src, dst);
if (cpu_state.flags & D_FLAG) { EDI--; ESI--; }
else { EDI++; ESI++; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1);
return 0;
}
static int opCMPSW_a16(uint32_t fetchdat)
{
uint16_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmemw(cpu_state.ea_seg->base, SI);
dst = readmemw(es, DI); if (cpu_state.abrt) return 1;
setsub16(src, dst);
if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
else { DI += 2; SI += 2; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0);
return 0;
}
static int opCMPSW_a32(uint32_t fetchdat)
{
uint16_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmemw(cpu_state.ea_seg->base, ESI);
dst = readmemw(es, EDI); if (cpu_state.abrt) return 1;
setsub16(src, dst);
if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; }
else { EDI += 2; ESI += 2; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1);
return 0;
}
static int opCMPSL_a16(uint32_t fetchdat)
{
uint32_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmeml(cpu_state.ea_seg->base, SI);
dst = readmeml(es, DI); if (cpu_state.abrt) return 1;
setsub32(src, dst);
if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; }
else { DI += 4; SI += 4; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 0);
return 0;
}
static int opCMPSL_a32(uint32_t fetchdat)
{
uint32_t src, dst;
SEG_CHECK_READ(cpu_state.ea_seg);
SEG_CHECK_READ(&cpu_state.seg_es);
src = readmeml(cpu_state.ea_seg->base, ESI);
dst = readmeml(es, EDI); if (cpu_state.abrt) return 1;
setsub32(src, dst);
if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; }
else { EDI += 4; ESI += 4; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 1);
return 0;
}
static int opSTOSB_a16(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememb(es, DI, AL); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI--;
else DI++;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
return 0;
}
static int opSTOSB_a32(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememb(es, EDI, AL); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI--;
else EDI++;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1);
return 0;
}
static int opSTOSW_a16(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememw(es, DI, AX); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI -= 2;
else DI += 2;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
return 0;
}
static int opSTOSW_a32(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememw(es, EDI, AX); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI -= 2;
else EDI += 2;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1);
return 0;
}
static int opSTOSL_a16(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememl(es, DI, EAX); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI -= 4;
else DI += 4;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0);
return 0;
}
static int opSTOSL_a32(uint32_t fetchdat)
{
SEG_CHECK_WRITE(&cpu_state.seg_es);
writememl(es, EDI, EAX); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI -= 4;
else EDI += 4;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 1);
return 0;
}
static int opLODSB_a16(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
AL = temp;
if (cpu_state.flags & D_FLAG) SI--;
else SI++;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opLODSB_a32(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
AL = temp;
if (cpu_state.flags & D_FLAG) ESI--;
else ESI++;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1);
return 0;
}
static int opLODSW_a16(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
AX = temp;
if (cpu_state.flags & D_FLAG) SI -= 2;
else SI += 2;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opLODSW_a32(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
AX = temp;
if (cpu_state.flags & D_FLAG) ESI -= 2;
else ESI += 2;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1);
return 0;
}
static int opLODSL_a16(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
EAX = temp;
if (cpu_state.flags & D_FLAG) SI -= 4;
else SI += 4;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0);
return 0;
}
static int opLODSL_a32(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
EAX = temp;
if (cpu_state.flags & D_FLAG) ESI -= 4;
else ESI += 4;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 1);
return 0;
}
static int opSCASB_a16(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmemb(es, DI); if (cpu_state.abrt) return 1;
setsub8(AL, temp);
if (cpu_state.flags & D_FLAG) DI--;
else DI++;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opSCASB_a32(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmemb(es, EDI); if (cpu_state.abrt) return 1;
setsub8(AL, temp);
if (cpu_state.flags & D_FLAG) EDI--;
else EDI++;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1);
return 0;
}
static int opSCASW_a16(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmemw(es, DI); if (cpu_state.abrt) return 1;
setsub16(AX, temp);
if (cpu_state.flags & D_FLAG) DI -= 2;
else DI += 2;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opSCASW_a32(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmemw(es, EDI); if (cpu_state.abrt) return 1;
setsub16(AX, temp);
if (cpu_state.flags & D_FLAG) EDI -= 2;
else EDI += 2;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1);
return 0;
}
static int opSCASL_a16(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmeml(es, DI); if (cpu_state.abrt) return 1;
setsub32(EAX, temp);
if (cpu_state.flags & D_FLAG) DI -= 4;
else DI += 4;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,0, 0);
return 0;
}
static int opSCASL_a32(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(&cpu_state.seg_es);
temp = readmeml(es, EDI); if (cpu_state.abrt) return 1;
setsub32(EAX, temp);
if (cpu_state.flags & D_FLAG) EDI -= 4;
else EDI += 4;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,0, 1);
return 0;
}
static int opINSB_a16(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
temp = inb(DX);
writememb(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI--;
else DI++;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opINSB_a32(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
temp = inb(DX);
writememb(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI--;
else EDI++;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opINSW_a16(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
temp = inw(DX);
writememw(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI -= 2;
else DI += 2;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opINSW_a32(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
temp = inw(DX);
writememw(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI -= 2;
else EDI += 2;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opINSL_a16(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
temp = inl(DX);
writememl(es, DI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) DI -= 4;
else DI += 4;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 0,1,0,1, 0);
return 0;
}
static int opINSL_a32(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
temp = inl(DX);
writememl(es, EDI, temp); if (cpu_state.abrt) return 1;
if (cpu_state.flags & D_FLAG) EDI -= 4;
else EDI += 4;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 0,1,0,1, 1);
return 0;
}
static int opOUTSB_a16(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
if (cpu_state.flags & D_FLAG) SI--;
else SI++;
outb(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opOUTSB_a32(uint32_t fetchdat)
{
uint8_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
if (cpu_state.flags & D_FLAG) ESI--;
else ESI++;
outb(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opOUTSW_a16(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
if (cpu_state.flags & D_FLAG) SI -= 2;
else SI += 2;
outw(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opOUTSW_a32(uint32_t fetchdat)
{
uint16_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
if (cpu_state.flags & D_FLAG) ESI -= 2;
else ESI += 2;
outw(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1);
return 0;
}
static int opOUTSL_a16(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
if (cpu_state.flags & D_FLAG) SI -= 4;
else SI += 4;
outl(EDX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 0,1,0,1, 0);
return 0;
}
static int opOUTSL_a32(uint32_t fetchdat)
{
uint32_t temp;
SEG_CHECK_READ(cpu_state.ea_seg);
temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
if (cpu_state.flags & D_FLAG) ESI -= 4;
else ESI += 4;
outl(EDX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 0,1,0,1, 1);
return 0;
}

View File

@@ -1,228 +0,0 @@
static int opXCHG_b_a16(uint32_t fetchdat)
{
uint8_t temp;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int opXCHG_b_a32(uint32_t fetchdat)
{
uint8_t temp;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int opXCHG_w_a16(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
}
static int opXCHG_w_a32(uint32_t fetchdat)
{
uint16_t temp;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
return 0;
}
static int opXCHG_l_a16(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
}
static int opXCHG_l_a32(uint32_t fetchdat)
{
uint32_t temp;
fetch_ea_32(fetchdat);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
}
static int opXCHG_AX_BX(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = BX;
BX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_CX(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = CX;
CX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_DX(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = DX;
DX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_SI(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = SI;
SI = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_DI(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = DI;
DI = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_BP(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = BP;
BP = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_AX_SP(uint32_t fetchdat)
{
uint16_t temp = AX;
AX = SP;
SP = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_EBX(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = EBX;
EBX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_ECX(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = ECX;
ECX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_EDX(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = EDX;
EDX = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_ESI(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = ESI;
ESI = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_EDI(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = EDI;
EDI = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_EBP(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = EBP;
EBP = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opXCHG_EAX_ESP(uint32_t fetchdat)
{
uint32_t temp = EAX;
EAX = ESP;
ESP = temp;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
}
#define opBSWAP(reg) \
static int opBSWAP_ ## reg(uint32_t fetchdat) \
{ \
reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \
CLOCK_CYCLES(1); \
PREFETCH_RUN(1, 1, -1, 0,0,0,0, 0); \
return 0; \
}
opBSWAP(EAX)
opBSWAP(EBX)
opBSWAP(ECX)
opBSWAP(EDX)
opBSWAP(ESI)
opBSWAP(EDI)
opBSWAP(EBP)
opBSWAP(ESP)

View File

@@ -24,13 +24,13 @@
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../device.h"
#include "../timer.h"
#include "../machine/machine.h"
#include "../mem.h"
#include "../nvr.h"
#include "device.h"
#include "timer.h"
#include "machine.h"
#include "mem.h"
#include "nvr.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
@@ -108,8 +108,8 @@ static void seg_reset(x86seg *s)
if(s == &cpu_state.seg_cs)
{
// TODO - When the PC is reset, initialization of the CS descriptor must be like the annotated line below.
//s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0;
s->base = AT ? 0xF0000 : 0xFFFF0;
s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0;
// s->base = AT ? 0xF0000 : 0xFFFF0;
s->seg = AT ? 0xF000 : 0xFFFF;
}
else
@@ -765,6 +765,7 @@ void loadcsjmp(uint16_t seg, uint32_t old_pc)
x86gpf(NULL,seg2&~3);
return;
}
/*FALLTHROUGH*/
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
CS=seg2;
do_seg_load(&cpu_state.seg_cs, segdat);
@@ -1235,6 +1236,7 @@ void loadcscall(uint16_t seg)
x86gpf(NULL,seg2&~3);
return;
}
/*FALLTHROUGH*/
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
CS=seg2;
do_seg_load(&cpu_state.seg_cs, segdat);
@@ -1766,6 +1768,7 @@ void pmodeint(int num, int soft)
x86gpf(NULL,seg&~3);
return;
}
/*FALLTHROUGH*/
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
if (!(segdat2[2]&0x8000))
{

View File

@@ -1,84 +0,0 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#define fplog 0
#include <math.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "cpu.h"
#include "../mem.h"
#include "../pic.h"
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "x87.h"
#include "386_common.h"
#ifdef ENABLE_FPU_LOG
int fpu_do_log = ENABLE_FPU_LOG;
static void
fpu_log(const char *fmt, ...)
{
va_list ap;
if (fpu_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define fpu_log(fmt, ...)
#endif
uint16_t x87_gettag()
{
uint16_t ret = 0;
int c;
for (c = 0; c < 8; c++)
{
if (cpu_state.tag[c] & TAG_UINT64)
ret |= 2 << (c*2);
else
ret |= (cpu_state.tag[c] << (c*2));
}
return ret;
}
void x87_settag(uint16_t new_tag)
{
cpu_state.tag[0] = new_tag & 3;
cpu_state.tag[1] = (new_tag >> 2) & 3;
cpu_state.tag[2] = (new_tag >> 4) & 3;
cpu_state.tag[3] = (new_tag >> 6) & 3;
cpu_state.tag[4] = (new_tag >> 8) & 3;
cpu_state.tag[5] = (new_tag >> 10) & 3;
cpu_state.tag[6] = (new_tag >> 12) & 3;
cpu_state.tag[7] = (new_tag >> 14) & 3;
}
#ifdef ENABLE_808X_LOG
void x87_dumpregs()
{
if (cpu_state.ismmx)
{
fpu_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q);
fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q);
}
else
{
fpu_log("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
fpu_log("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]);
}
fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag());
}
#endif

View File

@@ -1,26 +0,0 @@
uint32_t x87_pc_off,x87_op_off;
uint16_t x87_pc_seg,x87_op_seg;
static __inline void x87_set_mmx()
{
uint64_t *p;
cpu_state.TOP = 0;
p = (uint64_t *)cpu_state.tag;
*p = 0;
cpu_state.ismmx = 1;
}
static __inline void x87_emms()
{
uint64_t *p;
p = (uint64_t *)cpu_state.tag;
*p = 0;
cpu_state.ismmx = 0;
}
uint16_t x87_gettag();
void x87_settag(uint16_t new_tag);
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
#define TAG_UINT64 (1 << 2)

335
src/cpu_common/386.c Normal file
View File

@@ -0,0 +1,335 @@
#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.h"
#include "cpu.h"
#include "timer.h"
#include "x86.h"
#include "x87.h"
#include "nmi.h"
#include "mem.h"
#include "pic.h"
#include "pit.h"
#include "fdd.h"
#include "fdc.h"
#include "386_common.h"
#ifdef USE_NEW_DYNAREC
#include "codegen.h"
#endif
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
extern int codegen_flags_changed;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int timetolive;
uint16_t oldcs;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t oxpc;
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg _oldds;
#ifdef ENABLE_386_LOG
int x386_do_log = ENABLE_386_LOG;
void
x386_log(const char *fmt, ...)
{
va_list ap;
if (x386_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_log(fmt, ...)
#endif
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
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;
// pc++;
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);
}
}
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);
}
}
#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 0; }
#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 0
#include "x86_flags.h"
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "x86_ops.h"
void
exec386(int cycs)
{
// uint8_t opcode;
int vector, tempi, cycdiff, oldcyc;
int cycle_period, ins_cycles;
uint32_t addr;
cycles += cycs;
while (cycles > 0) {
cycle_period = (timer_target - (uint32_t)tsc) + 1;
x86_was_reset = 0;
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
oldcs=CS;
oldcpl=CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
#ifndef USE_NEW_DYNAREC
x86_was_reset = 0;
#endif
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(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;
}
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
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;
#ifndef USE_NEW_DYNAREC
CS = oldcs;
#endif
cpu_state.pc = cpu_state.oldpc;
x386_log("Double fault %i\n", ins);
pmodeint(8, 0);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_LOG
x386_log("Triple fault - reset\n");
#endif
}
}
}
ins_cycles -= cycles;
tsc += ins_cycles;
cycdiff = oldcyc - cycles;
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;
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) {
flags_rebuild();
if (msw & 1)
pmodeint(vector, 0);
else {
writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags);
writememw(ss, (SP - 4) & 0xFFFF, CS);
writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
SP -= 6;
addr = (vector << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = readmemw(0, addr);
loadcs(readmemw(0, addr + 2));
}
}
}
ins++;
if (timetolive) {
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process();
}
}
}

View File

@@ -9,17 +9,17 @@
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../timer.h"
#include "timer.h"
#include "x86.h"
#include "x87.h"
#include "../nmi.h"
#include "../mem.h"
#include "../pic.h"
#include "../pit.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "nmi.h"
#include "mem.h"
#include "pic.h"
#include "pit.h"
#include "fdd.h"
#include "fdc.h"
#include "386_common.h"
#include "x86_flags.h"
#include "codegen.h"
@@ -45,7 +45,11 @@ int cpl_override=0;
int fpucount=0;
#ifdef USE_NEW_DYNAREC
uint16_t cpu_cur_status = 0;
#else
uint32_t cpu_cur_status = 0;
#endif
uint32_t pccache;
uint8_t *pccache2;
@@ -117,6 +121,9 @@ void x86_int(int num)
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
#ifndef USE_NEW_DYNAREC
oxpc=cpu_state.pc;
#endif
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
@@ -161,6 +168,9 @@ void x86_int_sw(int num)
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
#ifndef USE_NEW_DYNAREC
oxpc=cpu_state.pc;
#endif
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
cycles -= timing_int_rm;
@@ -197,6 +207,9 @@ int x86_int_sw_rm(int num)
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = new_pc;
loadcs(new_cs);
#ifndef USE_NEW_DYNAREC
oxpc=cpu_state.pc;
#endif
cycles -= timing_int_rm;
trap = 0;
@@ -220,7 +233,11 @@ int checkio(int port)
if (cpu_state.abrt) return 0;
if ((t+(port>>3))>tr.limit) return 1;
cpl_override = 1;
#ifdef USE_NEW_DYNAREC
d = readmembl(tr.base + t + (port >> 3));
#else
d = readmemb386l(0, tr.base + t + (port >> 3));
#endif
cpl_override = 0;
return d&(1<<(port&7));
}

View File

@@ -16,6 +16,20 @@
* Copyright 2016-2019 Miran Grca.
*/
#ifndef _386_COMMON_H_
#define _386_COMMON_H_
#ifdef USE_NEW_DYNAREC
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#else
#undef readmemb
#undef writememb
@@ -28,8 +42,24 @@
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#endif
int checkio(int port);
#ifdef USE_NEW_DYNAREC
#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) return 1; \
if (tempi) \
{ \
x86gpf("check_io_perm(): no permission",0); \
return 1; \
} \
}
#else
#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (cpu_state.eflags&VM_FLAG))) \
{ \
int tempi = checkio(port); \
@@ -40,6 +70,7 @@
return 1; \
} \
}
#endif
#define SEG_CHECK_READ(seg) \
do \
@@ -205,7 +236,6 @@ static __inline uint32_t fastreadl(uint32_t a)
return 0;
pccache2 = t;
pccache=a>>12;
/* return *((uint32_t *)&pccache2[a]); */
}
return *((uint32_t *)&pccache2[a]);
}
@@ -309,19 +339,36 @@ static __inline void seteaq(uint64_t v)
{
if (seteaq_cwc())
return;
#ifdef USE_NEW_DYNAREC
writememql(easeg + cpu_state.eaaddr, v);
#else
writememql(easeg, cpu_state.eaaddr, v);
#endif
}
#ifdef USE_NEW_DYNAREC
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
#else
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); if (eal_w) *(uint8_t *)eal_w=v; else { writememb386l(easeg,cpu_state.eaaddr,v); } } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); if (eal_w) *(uint16_t *)eal_w=v; else { writememwl(easeg,cpu_state.eaaddr,v); } } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else { writememll(easeg,cpu_state.eaaddr,v); } } else cpu_state.regs[cpu_rm].l=v
#endif
#ifdef USE_NEW_DYNAREC
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v);
#else
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v);
#endif
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
#endif

View File

@@ -8,31 +8,31 @@
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
#include "fdd.h"
#include "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
uint32_t cpu_cur_status = 0;
int cpu_reps, cpu_reps_latched;
int cpu_notreps, cpu_notreps_latched;
int inrecomp = 0, cpu_block_end = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
@@ -55,7 +55,7 @@ x386_dynarec_log(const char *fmt, ...)
}
}
#else
#define x86_dynarec_log (fmt, ...)
#define x386_dynarec_log(fmt, ...)
#endif
@@ -175,155 +175,6 @@ static __inline void fetch_ea_16_long(uint32_t rmdat)
#include "x86_flags.h"
void x86_int(int num)
{
uint32_t addr;
flags_rebuild();
cpu_state.pc=cpu_state.oldpc;
if (msw&1)
{
pmodeint(num,0);
}
else
{
addr = (num << 2) + idt.base;
if ((num << 2) + 3 > idt.limit)
{
if (idt.limit < 35)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Triple fault in real mode - reset\n");
#endif
}
else
x86_int(8);
}
else
{
if (stack32)
{
writememw(ss,ESP-2,cpu_state.flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,cpu_state.pc);
ESP-=6;
}
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;
}
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));
}
}
cycles-=70;
CPU_BLOCK_END();
}
void x86_int_sw(int num)
{
uint32_t addr;
flags_rebuild();
cycles -= timing_int;
if (msw&1)
{
pmodeint(num,1);
}
else
{
addr = (num << 2) + idt.base;
if ((num << 2) + 3 > idt.limit)
{
x86_int(13);
}
else
{
if (stack32)
{
writememw(ss,ESP-2,cpu_state.flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,cpu_state.pc);
ESP-=6;
}
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;
}
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));
cycles -= timing_int_rm;
}
}
trap = 0;
CPU_BLOCK_END();
}
int x86_int_sw_rm(int num)
{
uint32_t addr;
uint16_t new_pc, new_cs;
flags_rebuild();
cycles -= timing_int;
addr = num << 2;
new_pc = readmemw(0, addr);
new_cs = readmemw(0, addr + 2);
if (cpu_state.abrt) return 1;
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
if (cpu_state.abrt) {
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("abrt5\n");
#endif
return 1;
}
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
if (cpu_state.abrt) {
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("abrt6\n");
#endif
return 1;
}
SP-=6;
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = new_pc;
loadcs(new_cs);
oxpc=cpu_state.pc;
cycles -= timing_int_rm;
trap = 0;
CPU_BLOCK_END();
return 0;
}
void x86illegal()
{
x86_int(6);
}
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
@@ -411,94 +262,6 @@ static void prefetch_flush()
#define PREFETCH_FLUSH() prefetch_flush()
int checkio(int port)
{
uint16_t t;
uint8_t d;
cpl_override = 1;
t = readmemw(tr.base, 0x66);
cpl_override = 0;
if (cpu_state.abrt) return 0;
if ((t+(port>>3))>tr.limit) return 1;
cpl_override = 1;
d = readmemb386l(0, tr.base + t + (port >> 3));
cpl_override = 0;
return d&(1<<(port&7));
}
int xout=0;
#define divexcp() { \
x86_int(0); \
}
int divl(uint32_t val)
{
uint64_t num, quo;
uint32_t rem, quo32;
if (val==0)
{
divexcp();
return 1;
}
num=(((uint64_t)EDX)<<32)|EAX;
quo=num/val;
rem=num%val;
quo32=(uint32_t)(quo&0xFFFFFFFF);
if (quo!=(uint64_t)quo32)
{
divexcp();
return 1;
}
EDX=rem;
EAX=quo32;
return 0;
}
int idivl(int32_t val)
{
int64_t num, quo;
int32_t rem, quo32;
if (val==0)
{
divexcp();
return 1;
}
num=(((uint64_t)EDX)<<32)|EAX;
quo=num/val;
rem=num%val;
quo32=(int32_t)(quo&0xFFFFFFFF);
if (quo!=(int64_t)quo32)
{
divexcp();
return 1;
}
EDX=rem;
EAX=quo32;
return 0;
}
void cpu_386_flags_extract()
{
flags_extract();
}
void cpu_386_flags_rebuild()
{
flags_rebuild();
}
int oldi;
uint32_t testr[9];
int dontprint=0;
void enter_smm()
{
uint32_t smram_state = smbase + 0xfe00;
@@ -510,6 +273,7 @@ void enter_smm()
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);
@@ -704,6 +468,7 @@ void leave_smm()
= 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;
@@ -716,11 +481,12 @@ void leave_smm()
#include "386_ops.h"
#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(cpu_state.flags & T_FLAG))
#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;

View File

@@ -8,26 +8,37 @@
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
#include "fdd.h"
#include "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;
@@ -48,15 +59,6 @@ x386_dynarec_log(const char *fmt, ...)
#endif
#define CPU_BLOCK_END() cpu_block_end = 1
int inrecomp = 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;
int cpu_block_end = 0;
static __inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
@@ -271,6 +273,7 @@ void enter_smm()
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);
@@ -465,6 +468,7 @@ void leave_smm()
= 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;
@@ -476,6 +480,7 @@ void leave_smm()
#include "386_ops.h"
#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
#ifdef USE_DYNAREC
@@ -484,30 +489,44 @@ static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
int vector;
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 += cyc_period;
cycles_start = cycles;
while (cycles>0)
{
oldcyc=cycles;
if (!CACHE_ON()) /*Interpret block*/
{
cpu_block_end = 0;
x86_was_reset = 0;
while (!cpu_block_end)
{
while (cycles>0)
{
#ifndef USE_NEW_DYNAREC
oldcs = CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cycdiff=0;
#endif
oldcyc=cycles;
if (!CACHE_ON()) /*Interpret block*/
{
cpu_block_end = 0;
x86_was_reset = 0;
while (!cpu_block_end)
{
#ifndef USE_NEW_DYNAREC
oldcs = CS;
oldcpl = CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
@@ -518,13 +537,17 @@ void exec386_dynarec(int cycs)
if (!cpu_state.abrt)
{
uint8_t opcode = fetchdat & 0xFF;
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
}
}
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
if (((cs + cpu_state.pc) >> 12) != pccache)
CPU_BLOCK_END();
@@ -536,74 +559,104 @@ void exec386_dynarec(int cycs)
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);
}
}
else
{
uint32_t phys_addr = get_phys(cs+cpu_state.pc);
int hash = HASH(phys_addr);
#ifdef USE_NEW_DYNAREC
codeblock_t *block = &codeblock[codeblock_hash[hash]];
int valid_block = 0;
#else
codeblock_t *block = codeblock_hash[hash];
#endif
int valid_block = 0;
#ifdef USE_NEW_DYNAREC
if (!cpu_state.abrt)
{
page_t *page = &pages[phys_addr >> 12];
#else
trap = 0;
/*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 (block && !cpu_state.abrt)
#endif
{
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);
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
#ifdef USE_NEW_DYNAREC
int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f);
if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_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));
#else
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
#endif
{
/*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;
#ifdef USE_NEW_DYNAREC
codeblock_hash[hash] = get_block_nr(block);
#endif
}
}
}
}
}
}
}
if (valid_block && (block->page_mask & *block->dirty_mask))
{
if (valid_block && (block->page_mask & *block->dirty_mask))
{
#ifdef USE_NEW_DYNAREC
codegen_check_flush(page, page->dirty_mask, phys_addr);
if (block->pc == BLOCK_PC_INVALID)
valid_block = 0;
else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
}
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.*/
#else
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;
#endif
}
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.*/
#ifdef USE_NEW_DYNAREC
uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400));
page_t *page_2 = &pages[phys_addr_2 >> 12];
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
valid_block = 0;
#else
uint32_t phys_addr_2 = get_phys_noabrt(block->endpc);
#endif
page_t *page_2 = &pages[phys_addr_2 >> 12];
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
valid_block = 0;
#ifdef USE_NEW_DYNAREC
else if (block->page_mask2 & *block->dirty_mask2)
{
codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2);
@@ -612,7 +665,17 @@ void exec386_dynarec(int cycs)
else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
}
}
#else
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;
}
#endif
}
#ifdef USE_NEW_DYNAREC
if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST))
{
block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
@@ -622,68 +685,103 @@ void exec386_dynarec(int cycs)
block->flags |= CODEBLOCK_BYTE_MASK;
}
if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7))
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
#else
if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
#endif
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
#ifdef USE_NEW_DYNAREC
block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED);
}
}
#else
block->flags &= ~CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0;
#endif
}
}
#ifdef USE_NEW_DYNAREC
if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED))
{
void (*code)() = (void *)&block->data[BLOCK_START];
#else
if (valid_block && block->was_recompiled)
#endif
{
void (*code)() = (void *)&block->data[BLOCK_START];
inrecomp=1;
code();
inrecomp=0;
#ifndef USE_NEW_DYNAREC
codeblock_hash[hash] = block;
#endif
cpu_recomp_blocks++;
}
else if (valid_block && !cpu_state.abrt)
{
uint32_t start_pc = cs+cpu_state.pc;
inrecomp=1;
code();
inrecomp=0;
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
cpu_recomp_blocks++;
}
else if (valid_block && !cpu_state.abrt)
{
#ifdef USE_NEW_DYNAREC
start_pc = cs+cpu_state.pc;
const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
cpu_block_end = 0;
x86_was_reset = 0;
#else
start_pc = cpu_state.pc;
#endif
cpu_block_end = 0;
x86_was_reset = 0;
cpu_new_blocks++;
codegen_block_start_recompile(block);
codegen_in_recompile = 1;
while (!cpu_block_end)
{
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
while (!cpu_block_end)
{
#ifndef USE_NEW_DYNAREC
oldcs = CS;
oldcpl = CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
uint8_t opcode = fetchdat & 0xFF;
{
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);
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
if (x86_was_reset)
break;
}
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
/*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 (x86_was_reset)
break;
}
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
/*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*/
#ifdef USE_NEW_DYNAREC
if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
#else
if ((cpu_state.pc - start_pc) > 1000)
#endif
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
@@ -715,16 +813,22 @@ void exec386_dynarec(int cycs)
else if (!cpu_state.abrt)
{
/*Mark block but do not recompile*/
uint32_t start_pc = cs+cpu_state.pc;
start_pc = cs+cpu_state.pc;
#ifdef USE_NEW_DYNAREC
const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
#endif
cpu_block_end = 0;
cpu_block_end = 0;
x86_was_reset = 0;
codegen_block_init(phys_addr);
while (!cpu_block_end)
{
#ifndef USE_NEW_DYNAREC
oldcs=CS;
oldcpl = CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
@@ -736,7 +840,7 @@ void exec386_dynarec(int cycs)
if (!cpu_state.abrt)
{
uint8_t opcode = fetchdat & 0xFF;
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
@@ -749,11 +853,19 @@ void exec386_dynarec(int cycs)
break;
}
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
/*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*/
#ifdef USE_NEW_DYNAREC
if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
#else
if ((cpu_state.pc - start_pc) > 1000)
#endif
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
@@ -780,10 +892,11 @@ void exec386_dynarec(int cycs)
if (x86_was_reset)
codegen_reset();
}
#ifdef USE_NEW_DYNAREC
else
cpu_state.oldpc = cpu_state.pc;
}
#endif
}
cycdiff=oldcyc-cycles;
tsc += cycdiff;
@@ -798,7 +911,9 @@ void exec386_dynarec(int cycs)
{
cpu_state.abrt = 0;
cpu_state.pc = cpu_state.oldpc;
x386_dynarec_log("Double fault %i\n", ins);
#ifndef USE_NEW_DYNAREC
CS = oldcs;
#endif
pmodeint(8, 0);
if (cpu_state.abrt)
{
@@ -819,7 +934,9 @@ void exec386_dynarec(int cycs)
else if (trap)
{
#ifdef USE_NEW_DYNAREC
trap = 0;
#endif
flags_rebuild();
if (msw&1)
{
@@ -841,6 +958,9 @@ void exec386_dynarec(int cycs)
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear)
@@ -869,15 +989,19 @@ void exec386_dynarec(int cycs)
addr=vector<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
#ifndef USE_NEW_DYNAREC
oxpc=cpu_state.pc;
#endif
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);
}
}

1007
src/cpu_common/386_dynarec.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,900 @@
#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.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
#include "fdd.h"
#include "fdc.h"
#ifdef USE_DYNAREC
#include "codegen.h"
#ifdef USE_NEW_DYNAREC
#include "codegen_backend.h"
#endif
#endif
#include "386_common.h"
#define CPU_BLOCK_END() cpu_block_end = 1
int inrecomp = 0, cpu_block_end = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
#ifdef ENABLE_386_DYNAREC_LOG
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;
void
x386_dynarec_log(const char *fmt, ...)
{
va_list ap;
if (x386_dynarec_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_dynarec_log(fmt, ...)
#endif
static __inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (cpu_rm == 4)
{
uint8_t sib = rmdat >> 8;
switch (cpu_mod)
{
case 0:
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
cpu_state.pc++;
break;
case 1:
cpu_state.pc++;
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
break;
case 2:
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
cpu_state.pc += 5;
break;
}
/*SIB byte present*/
if ((sib & 7) == 5 && !cpu_mod)
cpu_state.eaaddr = getlong();
else if ((sib & 6) == 4 && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
}
else
{
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
if (cpu_mod)
{
if (cpu_rm == 5 && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1)
{
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
cpu_state.pc++;
}
else
{
cpu_state.eaaddr += getlong();
}
}
else if (cpu_rm == 5)
{
cpu_state.eaaddr = getlong();
}
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
static __inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (!cpu_mod && cpu_rm == 6)
{
cpu_state.eaaddr = getword();
}
else
{
switch (cpu_mod)
{
case 0:
cpu_state.eaaddr = 0;
break;
case 1:
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
break;
case 2:
cpu_state.eaaddr = getword();
break;
}
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
cpu_state.last_ea = cpu_state.eaaddr;
}
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; }
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1
#include "x86_flags.h"
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
- Cycles used for non-instruction memory accesses are counted and subtracted
from the total cycles taken
- Any remaining cycles are used to refill the prefetch queue.
Note that this is only used for 286 / 386 systems. It is disabled when the
internal cache on 486+ CPUs is enabled.
*/
static int prefetch_bytes = 0;
static int prefetch_prefixes = 0;
static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
{
int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l;
if (instr_cycles < mem_cycles)
instr_cycles = mem_cycles;
prefetch_bytes -= prefetch_prefixes;
prefetch_bytes -= bytes;
if (modrm != -1)
{
if (ea32)
{
if ((modrm & 7) == 4)
{
if ((modrm & 0x700) == 0x500)
prefetch_bytes -= 5;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 5;
}
else
{
if ((modrm & 0xc7) == 0x05)
prefetch_bytes -= 4;
else if ((modrm & 0xc0) == 0x40)
prefetch_bytes--;
else if ((modrm & 0xc0) == 0x80)
prefetch_bytes -= 4;
}
}
else
{
if ((modrm & 0xc7) == 0x06)
prefetch_bytes -= 2;
else if ((modrm & 0xc0) != 0xc0)
prefetch_bytes -= ((modrm & 0xc0) >> 6);
}
}
/* Fill up prefetch queue */
while (prefetch_bytes < 0)
{
prefetch_bytes += cpu_prefetch_width;
cycles -= cpu_prefetch_cycles;
}
/* Subtract cycles used for memory access by instruction */
instr_cycles -= mem_cycles;
while (instr_cycles >= cpu_prefetch_cycles)
{
prefetch_bytes += cpu_prefetch_width;
instr_cycles -= cpu_prefetch_cycles;
}
prefetch_prefixes = 0;
if (prefetch_bytes > 16)
prefetch_bytes = 16;
}
static void prefetch_flush()
{
prefetch_bytes = 0;
}
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0)
#define PREFETCH_PREFIX() do { if (cpu_prefetch_cycles) prefetch_prefixes++; } while (0)
#define PREFETCH_FLUSH() prefetch_flush()
void enter_smm()
{
uint32_t smram_state = smbase + 0xfe00;
uint32_t old_cr0 = cr0;
uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16);
cr0 &= ~0x8000000d;
cpu_state.flags = 2;
cpu_state.eflags = 0;
in_smm = 1;
mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
smi_latched = 1;
mem_writel_phys(smram_state + 0xf8, smbase);
mem_writel_phys(smram_state + 0x128, cr4);
mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit);
mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base);
mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access);
mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit);
mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base);
mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access);
mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit);
mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base);
mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access);
mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit);
mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base);
mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access);
mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit);
mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base);
mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access);
mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit);
mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base);
mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access);
mem_writel_phys(smram_state + 0x178, ldt.limit);
mem_writel_phys(smram_state + 0x17c, ldt.base);
mem_writel_phys(smram_state + 0x180, ldt.access);
mem_writel_phys(smram_state + 0x184, gdt.limit);
mem_writel_phys(smram_state + 0x188, gdt.base);
mem_writel_phys(smram_state + 0x18c, gdt.access);
mem_writel_phys(smram_state + 0x190, idt.limit);
mem_writel_phys(smram_state + 0x194, idt.base);
mem_writel_phys(smram_state + 0x198, idt.access);
mem_writel_phys(smram_state + 0x19c, tr.limit);
mem_writel_phys(smram_state + 0x1a0, tr.base);
mem_writel_phys(smram_state + 0x1a4, tr.access);
mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg);
mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg);
mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg);
mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg);
mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg);
mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg);
mem_writel_phys(smram_state + 0x1c0, ldt.seg);
mem_writel_phys(smram_state + 0x1c4, tr.seg);
mem_writel_phys(smram_state + 0x1c8, dr[7]);
mem_writel_phys(smram_state + 0x1cc, dr[6]);
mem_writel_phys(smram_state + 0x1d0, EAX);
mem_writel_phys(smram_state + 0x1d4, ECX);
mem_writel_phys(smram_state + 0x1d8, EDX);
mem_writel_phys(smram_state + 0x1dc, EBX);
mem_writel_phys(smram_state + 0x1e0, ESP);
mem_writel_phys(smram_state + 0x1e4, EBP);
mem_writel_phys(smram_state + 0x1e8, ESI);
mem_writel_phys(smram_state + 0x1ec, EDI);
mem_writel_phys(smram_state + 0x1f0, cpu_state.pc);
mem_writel_phys(smram_state + 0x1d0, old_flags);
mem_writel_phys(smram_state + 0x1f8, cr3);
mem_writel_phys(smram_state + 0x1fc, old_cr0);
ds = es = fs_seg = gs = ss = 0;
DS = ES = FS = GS = SS = 0;
cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit
= cpu_state.seg_ss.limit = 0xffffffff;
cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high
= cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff;
cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low
= cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0;
cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access
= cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93;
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked
= cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
CS = 0x3000;
cs = smbase;
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff;
cpu_state.seg_cs.limit_low = 0;
cpu_state.seg_cs.access = 0x93;
cpu_state.seg_cs.checked = 1;
cr4 = 0;
dr[7] = 0x400;
cpu_state.pc = 0x8000;
nmi_mask = 0;
}
void leave_smm()
{
uint32_t smram_state = smbase + 0xfe00;
smbase = mem_readl_phys(smram_state + 0xf8);
cr4 = mem_readl_phys(smram_state + 0x128);
cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130);
cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134);
cpu_state.seg_es.limit_low = cpu_state.seg_es.base;
cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138);
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c);
cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140);
cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base;
cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144);
cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148);
cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c);
cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base;
cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150);
cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154);
cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158);
cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base;
cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c);
cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160);
cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164);
cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base;
cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168);
cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c);
cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170);
cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base;
cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174);
ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178);
ldt.base = mem_readl_phys(smram_state + 0x17c);
ldt.limit_low = ldt.base;
ldt.access = mem_readl_phys(smram_state + 0x180);
gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184);
gdt.base = mem_readl_phys(smram_state + 0x188);
gdt.limit_low = gdt.base;
gdt.access = mem_readl_phys(smram_state + 0x18c);
idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190);
idt.base = mem_readl_phys(smram_state + 0x194);
idt.limit_low = idt.base;
idt.access = mem_readl_phys(smram_state + 0x198);
tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c);
tr.base = mem_readl_phys(smram_state + 0x1a0);
tr.limit_low = tr.base;
tr.access = mem_readl_phys(smram_state + 0x1a4);
ES = mem_readl_phys(smram_state + 0x1a8);
CS = mem_readl_phys(smram_state + 0x1ac);
SS = mem_readl_phys(smram_state + 0x1b0);
DS = mem_readl_phys(smram_state + 0x1b4);
FS = mem_readl_phys(smram_state + 0x1b8);
GS = mem_readl_phys(smram_state + 0x1bc);
ldt.seg = mem_readl_phys(smram_state + 0x1c0);
tr.seg = mem_readl_phys(smram_state + 0x1c4);
dr[7] = mem_readl_phys(smram_state + 0x1c8);
dr[6] = mem_readl_phys(smram_state + 0x1cc);
EAX = mem_readl_phys(smram_state + 0x1d0);
ECX = mem_readl_phys(smram_state + 0x1d4);
EDX = mem_readl_phys(smram_state + 0x1d8);
EBX = mem_readl_phys(smram_state + 0x1dc);
ESP = mem_readl_phys(smram_state + 0x1e0);
EBP = mem_readl_phys(smram_state + 0x1e4);
ESI = mem_readl_phys(smram_state + 0x1e8);
EDI = mem_readl_phys(smram_state + 0x1ec);
cpu_state.pc = mem_readl_phys(smram_state + 0x1f0);
uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4);
cpu_state.flags = new_flags & 0xffff;
cpu_state.eflags = new_flags >> 16;
cr3 = mem_readl_phys(smram_state + 0x1f8);
cr0 = mem_readl_phys(smram_state + 0x1fc);
cpu_state.seg_cs.access &= ~0x60;
cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss
if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG))
{
cpu_state.seg_cs.checked = CS ? 1 : 0;
cpu_state.seg_ds.checked = DS ? 1 : 0;
cpu_state.seg_es.checked = ES ? 1 : 0;
cpu_state.seg_fs.checked = FS ? 1 : 0;
cpu_state.seg_gs.checked = GS ? 1 : 0;
cpu_state.seg_ss.checked = SS ? 1 : 0;
}
else
{
cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked
= cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
}
mem_restore_mem_state(smbase, 131072);
in_smm = 0;
nmi_mask = 1;
}
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"
#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
#ifdef USE_DYNAREC
static int cycles_main = 0;
void exec386_dynarec(int cycs)
{
int vector;
uint32_t addr;
int tempi;
int cycdiff;
int oldcyc;
uint32_t start_pc = 0;
int cyc_period = cycs / 2000; /*5us*/
cycles_main += cycs;
while (cycles_main > 0)
{
int cycles_start;
cycles += cyc_period;
cycles_start = cycles;
while (cycles>0)
{
oldcs = CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl = CPL;
cpu_state.op32 = use32;
cycdiff=0;
oldcyc=cycles;
if (!CACHE_ON()) /*Interpret block*/
{
cpu_block_end = 0;
x86_was_reset = 0;
while (!cpu_block_end)
{
oldcs = CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
}
if (!use32) cpu_state.pc &= 0xffff;
if (((cs + cpu_state.pc) >> 12) != pccache)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (cpu_state.abrt)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
ins++;
}
}
else
{
uint32_t phys_addr = get_phys(cs+cpu_state.pc);
int hash = HASH(phys_addr);
codeblock_t *block = codeblock_hash[hash];
int valid_block = 0;
trap = 0;
if (block && !cpu_state.abrt)
{
page_t *page = &pages[phys_addr >> 12];
/*Block must match current CS, PC, code segment size,
and physical address. The physical address check will
also catch any page faults at this stage*/
valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
(block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (!valid_block)
{
uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
{
/*Walk page tree to see if we find the correct block*/
codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
if (new_block)
{
valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
(new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
if (valid_block)
block = new_block;
}
}
}
if (valid_block && (block->page_mask & *block->dirty_mask))
{
codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr);
page->dirty_mask[(phys_addr >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
if (valid_block && block->page_mask2)
{
/*We don't want the second page to cause a page
fault at this stage - that would break any
code crossing a page boundary where the first
page is present but the second isn't. Instead
allow the first page to be interpreted and for
the page fault to occur when the page boundary
is actually crossed.*/
uint32_t phys_addr_2 = get_phys_noabrt(block->endpc);
page_t *page_2 = &pages[phys_addr_2 >> 12];
if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
valid_block = 0;
else if (block->page_mask2 & *block->dirty_mask2)
{
codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2);
page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0;
if (!block->valid)
valid_block = 0;
}
}
if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
{
/*FPU top-of-stack does not match the value this block was compiled
with, re-compile using dynamic top-of-stack*/
block->flags &= ~CODEBLOCK_STATIC_TOP;
block->was_recompiled = 0;
}
}
if (valid_block && block->was_recompiled)
{
void (*code)() = (void *)&block->data[BLOCK_START];
codeblock_hash[hash] = block;
inrecomp=1;
code();
inrecomp=0;
if (!use32) cpu_state.pc &= 0xffff;
cpu_recomp_blocks++;
}
else if (valid_block && !cpu_state.abrt)
{
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
cpu_new_blocks++;
codegen_block_start_recompile(block);
codegen_in_recompile = 1;
while (!cpu_block_end)
{
oldcs = CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end_recompile(block);
if (x86_was_reset)
codegen_reset();
codegen_in_recompile = 0;
}
else if (!cpu_state.abrt)
{
/*Mark block but do not recompile*/
start_pc = cpu_state.pc;
cpu_block_end = 0;
x86_was_reset = 0;
codegen_block_init(phys_addr);
while (!cpu_block_end)
{
oldcs=CS;
oldcpl = CPL;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
codegen_endpc = (cs + cpu_state.pc) + 8;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
if (!use32) cpu_state.pc &= 0xffff;
/*Cap source code at 4000 bytes per block; this
will prevent any block from spanning more than
2 pages. In practice this limit will never be
hit, as host block size is only 2kB*/
if ((cpu_state.pc - start_pc) > 1000)
CPU_BLOCK_END();
if (in_smm && smi_line && is_pentium)
CPU_BLOCK_END();
if (trap)
CPU_BLOCK_END();
if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
if (cpu_state.abrt)
{
codegen_block_remove();
CPU_BLOCK_END();
}
ins++;
}
if (!cpu_state.abrt && !x86_was_reset)
codegen_block_end();
if (x86_was_reset)
codegen_reset();
}
}
cycdiff=oldcyc-cycles;
tsc += cycdiff;
if (cpu_state.abrt)
{
flags_rebuild();
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
cpu_state.pc = cpu_state.oldpc;
CS = oldcs;
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Double fault %i\n", ins);
#endif
pmodeint(8, 0);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_DYNAREC_LOG
x386_dynarec_log("Triple fault - reset\n");
#endif
}
}
}
if (in_smm && smi_line && is_pentium)
{
enter_smm();
}
else if (trap)
{
flags_rebuild();
if (msw&1)
{
pmodeint(1,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (1 << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
oldcs = CS;
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear)
{
nmi_auto_clear = 0;
nmi = 0;
}
}
else if ((cpu_state.flags&I_FLAG) && pic_intpending)
{
vector = picinterrupt();
if (vector != -1)
{
CPU_BLOCK_END();
flags_rebuild();
if (msw&1)
{
pmodeint(vector,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=vector<<2;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
oxpc=cpu_state.pc;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
cycles_main -= (cycles_start - cycles);
}
}
#endif

View File

@@ -7,17 +7,19 @@
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "x86_flags.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "codegen.h"
#include "../pic.h"
#define CPU_BLOCK_END() cpu_block_end = 1
@@ -54,8 +56,8 @@ static __inline void fetch_ea_16_long(uint32_t rmdat)
cpu_state.last_ea = cpu_state.eaaddr;
}
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
@@ -63,7 +65,8 @@ static __inline void fetch_ea_16_long(uint32_t rmdat)
#define PREFETCH_FLUSH()
#define OP_TABLE(name) dynarec_ops_ ## name
#define CLOCK_CYCLES(c)
#define CLOCK_CYCLES(c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"

View File

@@ -167,12 +167,14 @@ static int ILLEGAL(uint32_t fetchdat)
return 0;
}
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_AMD_K) || defined(USE_I686)))
static int internal_illegal(char *s)
{
cpu_state.pc = cpu_state.oldpc;
x86gpf(s, 0);
return cpu_state.abrt;
}
#endif
#ifdef ENABLE_386_DYNAREC_LOG
extern void x386_dynarec_log(const char *fmt, ...);
@@ -183,13 +185,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#endif
#include "x86seg.h"
# include "x86_ops_amd.h"
#include "x86_ops_arith.h"
#include "x86_ops_atomic.h"
#include "x86_ops_bcd.h"
#include "x86_ops_bit.h"
#include "x86_ops_bitscan.h"
#include "x86_ops_call.h"
#include "x86_ops_flag.h"
#include "x86_ops_fpu.h"
#include "x86_ops_inc_dec.h"
@@ -202,7 +202,6 @@ extern void x386_dynarec_log(const char *fmt, ...);
# include "x86_ops_i686.h"
#endif
#include "x86_ops_mmx.h"
#include "x86_ops_3dnow.h"
#include "x86_ops_mmx_arith.h"
#include "x86_ops_mmx_cmp.h"
#include "x86_ops_mmx_logic.h"
@@ -220,10 +219,15 @@ extern void x386_dynarec_log(const char *fmt, ...);
#include "x86_ops_rep.h"
#include "x86_ops_ret.h"
#include "x86_ops_set.h"
#include "x86_ops_shift.h"
#include "x86_ops_stack.h"
#include "x86_ops_string.h"
#include "x86_ops_xchg.h"
#include "x86_ops_call.h"
#include "x86_ops_shift.h"
#ifdef USE_NEW_DYNAREC
#include "x86_ops_amd.h"
#endif
#include "x86_ops_3dnow.h"
static int op0F_w_a16(uint32_t fetchdat)
@@ -905,6 +909,7 @@ const OpFn OP_TABLE(pentiummmx_0f)[1024] =
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
#ifdef USE_NEW_DYNAREC
const OpFn OP_TABLE(k6_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
@@ -1086,7 +1091,9 @@ const OpFn OP_TABLE(k62_0f)[1024] =
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
#endif
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
const OpFn OP_TABLE(c6x86mx_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
@@ -1177,6 +1184,7 @@ const OpFn OP_TABLE(c6x86mx_0f)[1024] =
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
@@ -1271,7 +1279,6 @@ const OpFn OP_TABLE(pentiumpro_0f)[1024] =
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
};
#if 0
const OpFn OP_TABLE(pentium2_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
@@ -1362,7 +1369,6 @@ const OpFn OP_TABLE(pentium2_0f)[1024] =
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
#endif
const OpFn OP_TABLE(pentium2d_0f)[1024] =
{

View File

@@ -23,17 +23,18 @@
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "../machine/machine.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "machine.h"
#include "86box_io.h"
#include "mem.h"
#include "rom.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
/* The opcode of the instruction currently being executed. */
uint8_t opcode;
@@ -58,7 +59,6 @@ int is8086 = 0;
/* Variables for handling the non-maskable interrupts. */
int nmi = 0, nmi_auto_clear = 0;
int nmi_enable = 1;
/* Was the CPU ever reset? */
int x86_was_reset = 0;
@@ -653,6 +653,13 @@ sign_extend(uint8_t data)
}
static uint32_t
sign_extend32(uint16_t data)
{
return data + (data < 0x8000 ? 0 : 0xffff0000);
}
/* Fetches the effective address from the prefetch queue according to MOD and R/M. */
static void
do_mod_rm(void)
@@ -937,7 +944,6 @@ reset_common(int hard)
cpu_state.flags = 2;
trap = 0;
ovr_seg = NULL;
in_lock = 0;
EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
@@ -946,6 +952,7 @@ reset_common(int hard)
resetreadlookup();
makemod1table();
resetmcr();
pfq_clear();
cpu_set_edx();
mmu_perm = 4;
pfq_size = (is8086) ? 6 : 4;
@@ -960,10 +967,12 @@ reset_common(int hard)
x86_was_reset = 1;
cpu_alt_reset = 0;
pfq_clear();
prefetching = 1;
takeint = 0;
cpu_ven_reset();
cpu_alu_op = 0;
}
@@ -1215,7 +1224,7 @@ jcc(uint8_t opcode, int cond)
wait(1, 0);
cpu_data = pfq_fetchb();
wait(1, 0);
if ((!cond) == (opcode & 0x01))
if ((!cond) == !!(opcode & 0x01))
jump_short();
}
@@ -1759,6 +1768,7 @@ execx86(int cycs)
uint8_t temp = 0, temp2;
uint16_t addr, tempw;
uint16_t new_cs, new_ip;
uint32_t result;
int bits;
cycles += cycs;
@@ -2741,17 +2751,25 @@ execx86(int cycs)
case 0x28: /* IMUL */
wait(1, 0);
if (opcode & 1) {
result = cpu_data;
mul(AX, cpu_data);
AX = cpu_data;
DX = cpu_dest;
cpu_data |= DX;
set_co_mul(DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff));
result = ((uint32_t) DX << 16) | AX;
if ((rmdat & 0x38) == 0x20)
set_co_mul(DX != 0x0000);
else
set_co_mul(result != sign_extend32(AX));
} else {
mul(AL, cpu_data);
AL = (uint8_t) cpu_data;
AH = (uint8_t) cpu_dest;
cpu_data |= AH;
set_co_mul(AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff));
if ((rmdat & 0x38) == 0x20)
set_co_mul(AH != 0x00);
else
set_co_mul(AX != sign_extend(AL));
}
/* NOTE: When implementing the V20, care should be taken to not change
the zero flag. */
@@ -2886,6 +2904,8 @@ execx86(int cycs)
if (noint)
noint = 0;
cpu_alu_op = 0;
}
ins++;

View File

@@ -0,0 +1,64 @@
/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Definitions for the code generator.
*
* Version: @(#)codegen_public.h 1.0.0 2020/01/27
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020 Miran Grca.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef _CODEGEN_PUBLIC_H_
#define _CODEGEN_PUBLIC_H_
#ifndef USE_NEW_DYNAREC
#define PAGE_MASK_INDEX_MASK 3
#define PAGE_MASK_INDEX_SHIFT 10
#define PAGE_MASK_SHIFT 4
#else
#define PAGE_MASK_SHIFT 6
#endif
#define PAGE_MASK_MASK 63
#ifdef USE_NEW_DYNAREC
#define BLOCK_PC_INVALID 0xffffffff
#define BLOCK_INVALID 0
#endif
extern void codegen_init();
#ifdef USE_NEW_DYNAREC
extern void codegen_close();
#endif
extern void codegen_flush();
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern int codegen_in_recompile;
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -18,63 +18,79 @@
* Copyright 2016-2018 leilei.
* Copyright 2016,2018 Miran Grca.
*/
#ifdef USE_NEW_DYNAREC
#include "../cpu_new/cpu.h"
#else
#ifndef EMU_CPU_H
# define EMU_CPU_H
enum {
CPU_8088, /* 808x class CPUs */
CPU_8086,
#ifdef USE_NEC_808X
CPU_V20, /* NEC 808x class CPUs - future proofing */
CPU_V30,
#endif
CPU_286, /* 286 class CPUs */
CPU_386SX, /* 386 class CPUs */
CPU_386DX,
CPU_IBM386SLC,
CPU_IBM486SLC,
CPU_IBM486BL,
CPU_RAPIDCAD,
CPU_486SLC,
CPU_486DLC,
CPU_i486SX, /* 486 class CPUs */
CPU_Am486SX,
CPU_Cx486S,
CPU_i486SX2,
CPU_Am486SX2,
CPU_i486DX,
CPU_i486DX2,
CPU_Am486DX,
CPU_Am486DX2,
CPU_Cx486DX,
CPU_Cx486DX2,
CPU_iDX4,
CPU_Am486DX4,
CPU_Cx486DX4,
CPU_Am5x86,
CPU_Cx5x86,
CPU_WINCHIP, /* 586 class CPUs */
#ifdef USE_NEW_DYNAREC
CPU_WINCHIP2,
#endif
CPU_PENTIUM,
CPU_PENTIUMMMX,
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
CPU_Cx6x86,
CPU_Cx6x86MX,
CPU_Cx6x86L,
CPU_CxGX1,
#endif
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
CPU_K5,
CPU_5K86,
CPU_K6,
#endif
#ifdef USE_NEW_DYNAREC
CPU_K6_2,
CPU_K6_2C,
CPU_K6_3,
CPU_K6_2P,
CPU_K6_3P,
#endif
CPU_CYRIX3S,
#if defined(DEV_BRANCH) && defined(USE_I686)
CPU_PENTIUMPRO, /* 686 class CPUs */
CPU_PENTIUM2,
CPU_PENTIUM2D,
#endif
CPU_MAX /* Only really needed to close the enum in a way independent of the #ifdef's. */
};
#define CPU_8088 0 /* 808x class CPUs */
#define CPU_8086 1
#define CPU_286 2 /* 286 class CPUs */
#define CPU_386SX 3 /* 386 class CPUs */
#define CPU_386DX 4
#define CPU_IBM386SLC 5
#define CPU_IBM486SLC 6
#define CPU_IBM486BL 7
#define CPU_RAPIDCAD 8
#define CPU_486SLC 9
#define CPU_486DLC 10
#define CPU_i486SX 11 /* 486 class CPUs */
#define CPU_Am486SX 12
#define CPU_Cx486S 13
#define CPU_i486DX 14
#define CPU_Am486DX 15
#define CPU_Cx486DX 16
#define CPU_iDX4 17
#define CPU_Cx5x86 18
#define CPU_WINCHIP 19 /* 586 class CPUs */
#define CPU_PENTIUM 20
#define CPU_PENTIUMMMX 21
#define CPU_Cx6x86 22
#define CPU_Cx6x86MX 23
#define CPU_Cx6x86L 24
#define CPU_CxGX1 25
#ifdef DEV_BRANCH
#ifdef USE_AMD_K
#define CPU_K5 26
#define CPU_5K86 27
#define CPU_K6 28
#endif
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
#define CPU_PENTIUMPRO 29 /* 686 class CPUs */
#if 0
# define CPU_PENTIUM2 30
# define CPU_PENTIUM2D 31
#else
# define CPU_PENTIUM2D 30
#endif
#endif
#endif
#define MANU_INTEL 0
#define MANU_AMD 1
#define MANU_CYRIX 2
#define MANU_IDT 3
#define MANU_NEC 4
#define CPU_SUPPORTS_DYNAREC 1
#define CPU_REQUIRES_DYNAREC 2
@@ -86,7 +102,6 @@ typedef struct {
int cpu_type;
int rspeed;
double multi;
int pci_speed;
uint32_t edx_reset;
uint32_t cpuid_model;
uint16_t cyrix_id;
@@ -96,6 +111,7 @@ typedef struct {
int8_t atclk_div;
} CPU;
extern CPU cpus_8088[];
extern CPU cpus_8086[];
extern CPU cpus_286[];
@@ -115,29 +131,33 @@ extern CPU cpus_i486[];
extern CPU cpus_Am486[];
extern CPU cpus_Cx486[];
extern CPU cpus_WinChip[];
#ifdef USE_NEW_DYNAREC
extern CPU cpus_WinChip_SS7[];
#endif
extern CPU cpus_Pentium5V[];
extern CPU cpus_Pentium5V50[];
extern CPU cpus_PentiumS5[];
extern CPU cpus_Pentium3V[];
extern CPU cpus_Pentium[];
#ifdef DEV_BRANCH
#ifdef USE_AMD_K
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
extern CPU cpus_K5[];
extern CPU cpus_K56[];
#endif
#ifdef USE_NEW_DYNAREC
extern CPU cpus_K56_SS7[];
#endif
#ifdef DEV_BRANCH
#ifdef USE_CYRIX_6X86
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
extern CPU cpus_6x863V[];
extern CPU cpus_6x86[];
#endif
#ifdef USE_NEW_DYNAREC
extern CPU cpus_6x86SS7[];
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
extern CPU cpus_Cyrix3[];
#if defined(DEV_BRANCH) && defined(USE_I686)
extern CPU cpus_PentiumPro[];
extern CPU cpus_Pentium2[];
extern CPU cpus_Pentium2D[];
#endif
extern CPU cpus_PentiumII[];
extern CPU cpus_PGA370[];
#endif
@@ -196,6 +216,7 @@ typedef union {
int16_t sw[4];
uint8_t b[8];
int8_t sb[8];
float f[2];
} MMX_REG;
typedef struct {
@@ -259,6 +280,16 @@ struct _cpustate_ {
new_npxc;
uint32_t last_ea;
#ifdef USE_NEW_DYNAREC
uint32_t old_fp_control, new_fp_control;
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_
uint16_t old_fp_control2, new_fp_control2;
#endif
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__
uint32_t trunc_fp_control;
#endif
#endif
x86seg seg_cs,
seg_ds,
seg_es,
@@ -279,9 +310,15 @@ struct _cpustate_ {
/*If the cpu_state.flags below are set in cpu_cur_status, they must be set in block->status.
Otherwise they are ignored*/
#ifdef USE_NEW_DYNAREC
#define CPU_STATUS_NOTFLATDS (1 << 8)
#define CPU_STATUS_NOTFLATSS (1 << 9)
#define CPU_STATUS_MASK 0xff00
#else
#define CPU_STATUS_NOTFLATDS (1 << 16)
#define CPU_STATUS_NOTFLATSS (1 << 17)
#define CPU_STATUS_MASK 0xffff0000
#endif
#ifdef __MSC__
# define COMPILE_TIME_ASSERT(expr) /*nada*/
@@ -338,12 +375,13 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128)
/* Global variables. */
extern int cpu_iscyrix;
extern int cpu_16bitbus;
extern int cpu_busspeed;
extern int cpu_busspeed, cpu_pci_speed;
extern int cpu_multi;
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;
extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4;
extern int isibmcpu;
extern int is_rapidcad;
extern int hasfpu;
@@ -355,12 +393,16 @@ extern int hasfpu;
#define CPU_FEATURE_CX8 (1 << 5)
#define CPU_FEATURE_3DNOW (1 << 6)
extern uint32_t cpu_features;
extern uint32_t cpu_features;
extern int in_smm, smi_line, smi_latched;
extern uint32_t smbase;
extern int in_smm, smi_line, smi_latched;
extern uint32_t smbase;
#ifdef USE_NEW_DYNAREC
extern uint16_t cpu_cur_status;
#else
extern uint32_t cpu_cur_status;
#endif
extern uint64_t cpu_CR4_mask;
extern uint64_t tsc;
extern msr_t msr;
@@ -379,7 +421,7 @@ extern int ins,output;
extern uint32_t pccache;
extern uint8_t *pccache2;
extern double bus_timing;
extern double bus_timing, pci_timing;
extern uint64_t pmc[2];
extern uint16_t temp_seg_data[4];
extern uint16_t cs_msr;
@@ -455,8 +497,14 @@ extern CPU cpus_acer[]; // FIXME: should be in machine file!
/* Functions. */
extern int cpu_has_feature(int feature);
#ifdef USE_NEW_DYNAREC
extern void loadseg_dynarec(uint16_t seg, x86seg *s);
extern int loadseg(uint16_t seg, x86seg *s);
extern void loadcs(uint16_t seg);
#else
extern void loadseg(uint16_t seg, x86seg *s);
extern void loadcs(uint16_t seg);
#endif
extern char *cpu_current_pc(char *bufp);
@@ -473,16 +521,24 @@ extern void codegen_reset(void);
extern void cpu_set_edx(void);
extern int divl(uint32_t val);
extern void execx86(int cycs);
extern void enter_smm();
extern void leave_smm();
extern void enter_smm();
extern void leave_smm();
extern void exec386(int cycs);
extern void exec386_dynarec(int cycs);
extern int idivl(int32_t val);
#ifdef USE_NEW_DYNAREC
extern void loadcscall(uint16_t seg, uint32_t old_pc);
extern void loadcsjmp(uint16_t seg, uint32_t old_pc);
extern void pmodeint(int num, int soft);
extern void pmoderetf(int is32, uint16_t off);
extern void pmodeiret(int is32);
#else
extern void loadcscall(uint16_t seg);
extern void loadcsjmp(uint16_t seg, uint32_t old_pc);
extern void pmodeint(int num, int soft);
extern void pmoderetf(int is32, uint16_t off);
extern void pmodeiret(int is32);
#endif
extern void resetmcr(void);
extern void resetx86(void);
extern void refreshread(void);
@@ -505,6 +561,7 @@ extern void x87_reset(void);
extern int cpu_effective, cpu_alt_reset;
extern void cpu_dynamic_switch(int new_cpu);
extern void cpu_ven_reset(void);
#endif /*EMU_CPU_H*/
#endif

View File

@@ -45,9 +45,9 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../machine/machine.h"
#include "machine.h"
CPU cpus_8088[] = {
@@ -55,10 +55,10 @@ CPU cpus_8088[] = {
{"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}
{"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[] = {
@@ -80,9 +80,9 @@ CPU cpus_8086[] = {
{"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, 2, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/12", CPU_8086, 12000000, 3, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/16", CPU_8086, 16000000, 4, 0, 0, 0, 0, 0, 0,0,0,0, 2},
{"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}
};
@@ -153,7 +153,6 @@ CPU cpus_i386DX[] = {
{"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},
{"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
@@ -226,6 +225,7 @@ CPU cpus_486DLC[] = {
{"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},
@@ -249,7 +249,7 @@ CPU cpus_Am486S1[] = {
{"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},
{"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},
@@ -284,8 +284,8 @@ CPU cpus_i486[] = {
{"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},
{"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
{"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},
@@ -328,13 +328,14 @@ CPU cpus_Cx486[] = {
{"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},
{"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},
@@ -370,7 +371,9 @@ CPU cpus_6x86[] = {
{"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},
@@ -398,6 +401,7 @@ CPU cpus_6x86[] = {
{"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*/
@@ -412,15 +416,18 @@ CPU cpus_WinChip[] = {
{"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},
@@ -444,6 +451,7 @@ CPU cpus_WinChip_SS7[] = {
{"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)*/
@@ -528,6 +536,8 @@ CPU cpus_Pentium[] = {
{"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},
@@ -548,6 +558,8 @@ CPU cpus_Pentium[] = {
{"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},
@@ -586,13 +598,17 @@ CPU cpus_K56[] = {
{"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},
@@ -621,15 +637,15 @@ CPU cpus_K56_SS7[] = {
{"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_2, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42},
{"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44},
{"K6-2/380", CPU_K6_2, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46},
{"K6-2/400", CPU_K6_2, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-2/450", CPU_K6_2, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-2/475", CPU_K6_2, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-2/500", CPU_K6_2, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"K6-2/533", CPU_K6_2, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
{"K6-2/550", CPU_K6_2, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
{"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},
@@ -645,6 +661,7 @@ CPU cpus_K56_SS7[] = {
{"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

743
src/cpu_common/cpu_table.c Normal file
View File

@@ -0,0 +1,743 @@
/*
* 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
*
* Version: @(#)cpu_table.c 1.0.7 2019/10/21
*
* 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.h"
#include "cpu.h"
#include "machine.h"
CPU cpus_8088[] = {
/*8088 standard*/
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 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, 1},
{"", -1, 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, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 7159092, 1, 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, 1},
{"", -1, 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, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/9.54", CPU_8086, 9545456, 1, 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, 1},
{"8086/12", CPU_8086, 12000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
{"8086/16", CPU_8086, 16000000, 1, 0, 0, 0, 0, 0,0,0,0, 2},
{"", -1, 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, 1},
{"", -1, 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, 2,2,2,2, 1},
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 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, 3,3,3,3, 1},
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 3,3,3,3, 1},
{"", -1, 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, 2,2,2,2, 1},
{"", -1, 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, 2,2,2,2, 1},
{"", -1, 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, 2,2,2,2, 1},
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_i386SX[] = {
/*i386SX*/
{"i386SX/16", CPU_386SX, 16000000, 1, 0x2308, 0, 0, 0, 3,3,3,3, 2},
{"i386SX/20", CPU_386SX, 20000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"i386SX/25", CPU_386SX, 25000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"i386SX/33", CPU_386SX, 33333333, 1, 0x2308, 0, 0, 0, 6,6,3,3, 4},
{"i386SX/40", CPU_386SX, 40000000, 1, 0x2308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_i386DX[] = {
/*i386DX/RapidCAD*/
{"i386DX/16", CPU_386DX, 16000000, 1, 0x0308, 0, 0, 0, 3,3,3,3, 2},
{"i386DX/20", CPU_386DX, 20000000, 1, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"i386DX/25", CPU_386DX, 25000000, 1, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"i386DX/33", CPU_386DX, 33333333, 1, 0x0308, 0, 0, 0, 6,6,3,3, 4},
{"i386DX/40", CPU_386DX, 40000000, 1, 0x0308, 0, 0, 0, 7,7,3,3, 5},
{"RapidCAD/25", CPU_RAPIDCAD, 25000000, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
{"RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
{"RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_Am386SX[] = {
/*Am386SX*/
{"Am386SX/16", CPU_386SX, 16000000, 1, 0x2308, 0, 0, 0, 3,3,3,3, 2},
{"Am386SX/20", CPU_386SX, 20000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"Am386SX/25", CPU_386SX, 25000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
{"Am386SX/33", CPU_386SX, 33333333, 1, 0x2308, 0, 0, 0, 6,6,3,3, 4},
{"Am386SX/40", CPU_386SX, 40000000, 1, 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, 0x0308, 0, 0, 0, 4,4,3,3, 3},
{"Am386DX/33", CPU_386DX, 33333333, 1, 0x0308, 0, 0, 0, 6,6,3,3, 4},
{"Am386DX/40", CPU_386DX, 40000000, 1, 0x0308, 0, 0, 0, 7,7,3,3, 5},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_486SLC[] = {
/*Cx486SLC*/
{"Cx486SLC/20", CPU_486SLC, 20000000, 1, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
{"Cx486SLC/25", CPU_486SLC, 25000000, 1, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
{"Cx486SLC/33", CPU_486SLC, 33333333, 1, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
{"Cx486SRx2/32", CPU_486SLC, 32000000, 2, 0x406, 0, 0x0006, 0, 6,6,6,6, 4},
{"Cx486SRx2/40", CPU_486SLC, 40000000, 2, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
{"Cx486SRx2/50", CPU_486SLC, 50000000, 2, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM386SLC[] = {
/*IBM 386SLC*/
{"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0x300, 0, 0, 0, 3,3,3,3, 2},
{"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0x300, 0, 0, 0, 4,4,3,3, 3},
{"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0x300, 0, 0, 0, 4,4,3,3, 3},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM486SLC[] = {
/*IBM 486SLC*/
{"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0x400, 0, 0, 0, 6,6,3,3, 4},
{"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0x400, 0, 0, 0, 7,7,6,6, 5},
{"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0x400, 0, 0, 0, 8,8,6,6, 6},
{"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0x400, 0, 0, 0, 12,12,6,6, 8},
{"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 7},
{"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 9},
{"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0x400, 0, 0, 0, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_IBM486BL[] = {
/*IBM Blue Lightning*/
{"486BL2/50", CPU_IBM486BL, 50000000, 2, 0x400, 0, 0, 0, 8,8,6,6, 6},
{"486BL2/66", CPU_IBM486BL, 66666666, 2, 0x400, 0, 0, 0, 12,12,6,6, 8},
{"486BL3/75", CPU_IBM486BL, 75000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 9},
{"486BL3/100", CPU_IBM486BL, 100000000, 3, 0x400, 0, 0, 0, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_486DLC[] = {
/*Cx486DLC*/
{"Cx486DLC/25", CPU_486DLC, 25000000, 1, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3},
{"Cx486DLC/33", CPU_486DLC, 33333333, 1, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4},
{"Cx486DLC/40", CPU_486DLC, 40000000, 1, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5},
{"Cx486DRx2/32", CPU_486DLC, 32000000, 2, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4},
{"Cx486DRx2/40", CPU_486DLC, 40000000, 2, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
{"Cx486DRx2/50", CPU_486DLC, 50000000, 2, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
{"Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0x407, 0, 0x0007, 0, 12,12,6,6, 8},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_i486S1[] = {
/*i486*/
{"i486SX/16", CPU_i486SX, 16000000, 1, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
{"i486SX/20", CPU_i486SX, 20000000, 1, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/25", CPU_i486SX, 25000000, 1, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/33", CPU_i486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486SX2/50", CPU_i486SX, 50000000, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
{"i486DX/25", CPU_i486DX, 25000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486DX/33", CPU_i486DX, 33333333, 1, 0x414, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486DX/50", CPU_i486DX, 50000000, 1, 0x411, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
{"i486DX2/40", CPU_i486DX, 40000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5},
{"i486DX2/50", CPU_i486DX, 50000000, 2, 0x433, 0x433, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486DX2/66", CPU_i486DX, 66666666, 2, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 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, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
};
CPU cpus_Am486S1[] = {
/*Am486*/
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486SX2/50", CPU_Am486SX2, 50000000, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
{"Am486SX2/66", CPU_Am486SX2, 66666666, 2, 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, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486DX2/50", CPU_Am486DX2, 50000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Am486DX2/66", CPU_Am486DX2, 66666666, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX2/80", CPU_Am486DX2, 80000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_Cx486S1[] = {
/*Cyrix 486*/
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX2/50", CPU_Cx486DX2, 50000000, 2, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Cx486DX2/66", CPU_Cx486DX2, 66666666, 2, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Cx486DX2/80", CPU_Cx486DX2, 80000000, 2, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_i486[] = {
/*i486/P24T*/
{"i486SX/16", CPU_i486SX, 16000000, 1, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
{"i486SX/20", CPU_i486SX, 20000000, 1, 0x420, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/25", CPU_i486SX, 25000000, 1, 0x422, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486SX/33", CPU_i486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486SX2/50", CPU_i486SX, 50000000, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
{"i486DX/25", CPU_i486DX, 25000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
{"i486DX/33", CPU_i486DX, 33333333, 1, 0x414, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
{"i486DX/50", CPU_i486DX, 50000000, 1, 0x411, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
{"i486DX2/40", CPU_i486DX, 40000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5},
{"i486DX2/50", CPU_i486DX, 50000000, 2, 0x433, 0x433, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
{"i486DX2/66", CPU_i486DX, 66666666, 2, 0x435, 0x435, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
{"iDX4/75", CPU_iDX4, 75000000, 3, 0x480, 0x480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/
{"iDX4/100", CPU_iDX4, 100000000, 3, 0x483, 0x483, 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, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9},
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
{"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
{"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 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}
};
CPU cpus_Am486[] = {
/*Am486/5x86*/
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486SX2/50", CPU_Am486SX2, 50000000, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
{"Am486SX2/66", CPU_Am486SX2, 66666666, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX/33", CPU_Am486DX, 33333333, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Am486DX2/50", CPU_Am486DX2, 50000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Am486DX2/66", CPU_Am486DX2, 66666666, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Am486DX2/80", CPU_Am486DX2, 80000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"Am486DX4/75", CPU_Am486DX4, 75000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
{"Am486DX4/90", CPU_Am486DX4, 90000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Am486DX4/100", CPU_Am486DX4, 100000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Am486DX4/120", CPU_Am486DX4, 120000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
{"Am5x86/P75", CPU_Am5x86, 133333333, 4, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
{"Am5x86/P75+", CPU_Am5x86, 150000000, 3, 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_Am5x86, 160000000, 4, 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}
};
CPU cpus_Cx486[] = {
/*Cyrix 486*/
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
{"Cx486DX2/50", CPU_Cx486DX2, 50000000, 2, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
{"Cx486DX2/66", CPU_Cx486DX2, 66666666, 2, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
{"Cx486DX2/80", CPU_Cx486DX2, 80000000, 2, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
{"Cx486DX4/75", CPU_Cx486DX4, 75000000, 3, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
{"Cx486DX4/100", CPU_Cx486DX4, 100000000, 3, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
/*Cyrix 5x86*/
{"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 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, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
{"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
{"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
{"", -1, 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, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 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}
};
CPU cpus_6x86[] = {
/*Cyrix 6x86*/
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86L*/
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86MX/MII*/
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 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}
};
#endif
#ifdef USE_NEW_DYNAREC
CPU cpus_6x86SS7[] = {
/*Cyrix 6x86*/
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86L*/
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
/*Cyrix 6x86MX/MII*/
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
{"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
{"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
{"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 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}
};
#endif
CPU cpus_WinChip[] = {
/*IDT WinChip*/
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
#ifdef USE_NEW_DYNAREC
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 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}
};
#ifdef USE_NEW_DYNAREC
CPU cpus_WinChip_SS7[] = {
/*IDT WinChip*/
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9},
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2},
{"WinChip 2A/266", CPU_WINCHIP2, 233333333, 7/3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28},
{"WinChip 2A/300", CPU_WINCHIP2, 250000000, 5/2, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30},
{"", -1, 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, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 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}
};
CPU cpus_Pentium5V50[] = {
/*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/
{"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6},
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
{"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12},
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 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}
};
CPU cpus_PentiumS5[] = {
/*Intel Pentium (Socket 5)*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
/*Intel Pentium OverDrive*/
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 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}
};
CPU cpus_Pentium3V[] = {
/*Intel Pentium*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 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, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 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}
};
CPU cpus_Pentium[] = {
/*Intel Pentium*/
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 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, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
/*Mobile Pentium*/
{"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 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, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 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}
};
#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, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 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, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 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, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 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}
};
CPU cpus_K56[] = {
/*AMD K5 (Socket 7)*/
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 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, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 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, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 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, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 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, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
{"K6-2/266", CPU_K6_2, 266666666, 4, 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, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
{"K6-2/366", CPU_K6_2, 366666666, 11/2, 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}
};
#endif
#ifdef USE_NEW_DYNAREC
CPU cpus_K56_SS7[] = {
/*AMD K5 (Socket 7)*/
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 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, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 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, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 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, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 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, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28},
{"K6-2/266", CPU_K6_2, 266666666, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32},
{"K6-2/300", CPU_K6_2, 300000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36},
{"K6-2/333", CPU_K6_2, 332500000, 7/2, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40},
{"K6-2/350", CPU_K6_2C, 350000000, 7/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42},
{"K6-2/366", CPU_K6_2C, 366666666, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44},
{"K6-2/380", CPU_K6_2C, 380000000, 4, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46},
{"K6-2/400", CPU_K6_2C, 400000000, 4, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-2/450", CPU_K6_2C, 450000000, 9/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-2/475", CPU_K6_2C, 475000000, 5, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-2/500", CPU_K6_2C, 500000000, 5, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"K6-2/533", CPU_K6_2C, 533333333, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
{"K6-2/550", CPU_K6_2C, 550000000, 11/2, 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, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-2+/475", CPU_K6_2P, 475000000, 5, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-2+/500", CPU_K6_2P, 500000000, 5, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
{"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
{"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
{"K6-III/400", CPU_K6_3, 400000000, 4, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-III/450", CPU_K6_3, 450000000, 9/2, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-III+/400", CPU_K6_3P, 400000000, 4, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
{"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
{"K6-III+/475", CPU_K6_3P, 475000000, 5, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
{"K6-III+/500", CPU_K6_3P, 500000000, 5, 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}
};
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
CPU cpus_PentiumPro[] = {
/*Intel Pentium Pro*/
{"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
{"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
{"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
{"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 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, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
{"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
{"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
{"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33},
{"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
{"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
{"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 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}
};
CPU cpus_PentiumII[] = {
/*Intel Pentium II Klamath*/
{"Pentium II Klamath 50", CPU_PENTIUM2, 50000000, 1, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium II Klamath 60", CPU_PENTIUM2, 60000000, 1, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium II Klamath 66", CPU_PENTIUM2, 66666666, 1, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium II Klamath 75", CPU_PENTIUM2, 75000000, 3/2, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium II Klamath 233", CPU_PENTIUM2, 233333333, 7/2, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
{"Pentium II Klamath 266", CPU_PENTIUM2, 266666666, 4, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
{"Pentium II Klamath 300/66", CPU_PENTIUM2, 300000000, 9/2, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
/*Intel Pentium II Deschutes*/
{"Pentium II Deschutes 50", CPU_PENTIUM2D, 50000000, 1, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
{"Pentium II Deschutes 60", CPU_PENTIUM2D, 60000000, 1, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
{"Pentium II Deschutes 66", CPU_PENTIUM2D, 66666666, 1, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
{"Pentium II Deschutes 75", CPU_PENTIUM2D, 75000000, 3/2, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
{"Pentium II Deschutes 266", CPU_PENTIUM2D, 266666666, 4, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
{"Pentium II Deschutes 300/66", CPU_PENTIUM2D, 300000000, 9/2, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
{"Pentium II Deschutes 333", CPU_PENTIUM2D, 333333333, 5, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
{"Pentium II Deschutes 350", CPU_PENTIUM2D, 350000000, 7/2, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,11,11, 42},
{"Pentium II Deschutes 400", CPU_PENTIUM2D, 400000000, 4, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48},
{"Pentium II Deschutes 450", CPU_PENTIUM2D, 450000000, 9/2, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
CPU cpus_PGA370[] = {
{"Celeron Mendocino 100", CPU_PENTIUM2D, 100000000, 3/2, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
{"Celeron Mendocino 333", CPU_PENTIUM2D, 333333333, 5, 0x665, 0x665, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
#endif
#endif
CPU cpus_Cyrix3[] = {
/*VIA Cyrix III (Samuel)*/
{"Cyrix III 66", CPU_CYRIX3S, 66666666, 1, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 8}, /*66 MHz version*/
{"Cyrix III 233", CPU_CYRIX3S, 233333333, 3.5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, 28},
{"Cyrix III 266", CPU_CYRIX3S, 266666666, 4, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 32},
{"Cyrix III 300", CPU_CYRIX3S, 300000000, 4.5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 27, 27, 13, 13, 36},
{"Cyrix III 333", CPU_CYRIX3S, 333333333, 5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 30, 30, 15, 15, 40},
{"Cyrix III 350", CPU_CYRIX3S, 350000000, 3.5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 32, 32, 11, 11, 42},
{"Cyrix III 400", CPU_CYRIX3S, 400000000, 4, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 36, 36, 12, 12, 48},
{"Cyrix III 450", CPU_CYRIX3S, 450000000, 4.5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 41, 41, 14, 14, 54}, /*^ is lower P2 speeds to allow emulation below 466 mhz*/
{"Cyrix III 500", CPU_CYRIX3S, 500000000, 5, 0x660, 0x660, 0, CPU_SUPPORTS_DYNAREC, 45, 45, 15, 15, 60},
{"Cyrix III 550", CPU_CYRIX3S, 550000000, 5.5, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC, 50, 50, 17, 17, 66},
{"Cyrix III 600", CPU_CYRIX3S, 600000000, 6, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC, 54, 54, 18, 18, 72},
{"Cyrix III 650", CPU_CYRIX3S, 650000000, 6.5, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC, 58, 58, 20, 20, 78},
{"Cyrix III 700", CPU_CYRIX3S, 700000000, 7, 0x662, 0x662, 0, CPU_SUPPORTS_DYNAREC, 62, 62, 21, 21, 84},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};

View File

@@ -85,13 +85,19 @@ extern const OpFn dynarec_ops_winchip2_0f[1024];
extern const OpFn dynarec_ops_pentium_0f[1024];
extern const OpFn dynarec_ops_pentiummmx_0f[1024];
extern const OpFn dynarec_ops_c6x86mx_0f[1024];
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
extern const OpFn dynarec_ops_c6x86mx_0f[1024];
#endif
#ifdef USE_NEW_DYNAREC
extern const OpFn dynarec_ops_k6_0f[1024];
extern const OpFn dynarec_ops_k62_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_I686)
extern const OpFn dynarec_ops_pentiumpro_0f[1024];
extern const OpFn dynarec_ops_pentium2_0f[1024];
extern const OpFn dynarec_ops_pentium2d_0f[1024];
#endif
@@ -179,13 +185,18 @@ extern const OpFn ops_winchip2_0f[1024];
extern const OpFn ops_pentium_0f[1024];
extern const OpFn ops_pentiummmx_0f[1024];
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
extern const OpFn ops_c6x86mx_0f[1024];
#endif
#ifdef USE_NEW_DYNAREC
extern const OpFn ops_k6_0f[1024];
extern const OpFn ops_k62_0f[1024];
#endif
#if defined(DEV_BRANCH) && defined(USE_I686)
extern const OpFn ops_pentiumpro_0f[1024];
extern const OpFn ops_pentium2_0f[1024];
extern const OpFn ops_pentium2d_0f[1024];
#endif

View File

@@ -99,7 +99,7 @@ static int opSAHF(uint32_t fetchdat)
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
#if 0
#ifdef USE_NEW_DYNAREC
codegen_flags_changed = 0;
#endif
@@ -182,7 +182,7 @@ static int opPOPF_286(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
#if 0
#ifdef USE_NEW_DYNAREC
codegen_flags_changed = 0;
#endif
@@ -242,7 +242,7 @@ static int opPOPF(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
#if 0
#ifdef USE_NEW_DYNAREC
codegen_flags_changed = 0;
#endif
@@ -276,7 +276,7 @@ static int opPOPFD(uint32_t fetchdat)
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0);
#if 0
#ifdef USE_NEW_DYNAREC
codegen_flags_changed = 0;
#endif

View File

@@ -8,10 +8,10 @@
*
* x86 i686 (Pentium Pro/Pentium II) CPU Instructions.
*
* Version: @(#)x86_ops_i686.h 1.0.5 2018/10/17
* Version: @(#)x86_ops_i686.h 1.0.6 2020/01/27
*
* Author: Miran Grca, <mgrca8@gmail.com>
* Copyright 2016-2018 Miran Grca.
* Copyright 2016-2020 Miran Grca.
*/
/* 0 = Limit 0-15
@@ -190,10 +190,14 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat)
{
/* FXRSTOR */
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
cpu_state.TOP = (fpus >> 11) & 7;
cpu_state.npxs &= fpus & ~0x3800;
@@ -316,7 +320,9 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat)
cpu_state.eaaddr = old_eaaddr;
cpu_state.npxc = 0x37F;
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag;
@@ -371,10 +377,14 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat)
{
/* FXRSTOR */
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
cpu_state.TOP = (fpus >> 11) & 7;
cpu_state.npxs &= fpus & ~0x3800;
@@ -497,7 +507,9 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat)
cpu_state.eaaddr = old_eaaddr;
cpu_state.npxc = 0x37F;
#ifdef USE_NEW_DYNAREC
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
#endif
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
cpu_state.npxs = 0;
p = (uint64_t *)cpu_state.tag;

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