diff --git a/.gitignore b/.gitignore index bac8fe436..cc9da153b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ src/*.o src/*.exe src/*.res +src/*.d src/NUL diff --git a/README.md b/README.md index c825e0c57..bc5246d72 100644 --- a/README.md +++ b/README.md @@ -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 `\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 `\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. diff --git a/src/86box.h b/src/86box.h index 477051461..30a5088e1 100644 --- a/src/86box.h +++ b/src/86box.h @@ -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, *f Fred N. van Kempen, * - * 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 diff --git a/src/io.h b/src/86box_io.h similarity index 100% rename from src/io.h rename to src/86box_io.h diff --git a/src/apm.c b/src/apm.c index 1ec2fb6de..27c33474e 100644 --- a/src/apm.c +++ b/src/apm.c @@ -21,9 +21,9 @@ #include #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 diff --git a/src/apm_new.c b/src/apm_new.c index a0963cade..2ae56d82e 100644 --- a/src/apm_new.c +++ b/src/apm_new.c @@ -21,9 +21,9 @@ #include #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 diff --git a/src/bugger.c b/src/bugger.c index cd2d843d9..7205ea25d 100644 --- a/src/bugger.c +++ b/src/bugger.c @@ -56,7 +56,7 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "device.h" #include "plat.h" #include "ui.h" diff --git a/src/cassette/cassette.c b/src/cassette/cassette.c deleted file mode 100644 index b9ba8a7ca..000000000 --- a/src/cassette/cassette.c +++ /dev/null @@ -1,203 +0,0 @@ -/************************************************************************ - - PCEM: IBM 5150 Cassette support - - Copyright (C) 2019 John Elliott - - 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 -#include -#include -#include -#include -#include -#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 -}; - diff --git a/src/cassette/cassette.h b/src/cassette/cassette.h deleted file mode 100644 index cf7712811..000000000 --- a/src/cassette/cassette.h +++ /dev/null @@ -1,30 +0,0 @@ -/************************************************************************ - - PCEM: IBM 5150 cassette support - - Copyright (C) 2019 John Elliott - - 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); diff --git a/src/cassette/pzx.c b/src/cassette/pzx.c deleted file mode 100644 index c7d16d36e..000000000 --- a/src/cassette/pzx.c +++ /dev/null @@ -1,414 +0,0 @@ -/************************************************************************ - - PCEM: IBM 5150 Cassette support - - Copyright (C) 2019 John Elliott - - 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 -#include -#include -#include -#include -#include -#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; -} - - - diff --git a/src/cassette/pzx.h b/src/cassette/pzx.h deleted file mode 100644 index a642a0688..000000000 --- a/src/cassette/pzx.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************ - - PCEM: IBM 5150 cassette support - - Copyright (C) 2019 John Elliott - - 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); diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index 6c19233a7..2b68ff09f 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -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, * @@ -22,12 +22,12 @@ #include #include #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) diff --git a/src/cdrom/cdrom.h b/src/cdrom/cdrom.h index ec141a5f9..e5b3a948f 100644 --- a/src/cdrom/cdrom.h +++ b/src/cdrom/cdrom.h @@ -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); diff --git a/src/cdrom/cdrom_image.c b/src/cdrom/cdrom_image.c index 34a2dcc29..2a4c7b30c 100644 --- a/src/cdrom/cdrom_image.c +++ b/src/cdrom/cdrom_image.c @@ -21,6 +21,7 @@ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#include #include #include #include @@ -28,10 +29,10 @@ #include #include #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; diff --git a/src/cdrom/cdrom_image_backend.c b/src/cdrom/cdrom_image_backend.c index 61260b44d..c85739b6c 100644 --- a/src/cdrom/cdrom_image_backend.c +++ b/src/cdrom/cdrom_image_backend.c @@ -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, * Fred N. van Kempen, @@ -35,8 +35,8 @@ #endif #include #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)); diff --git a/src/cdrom/cdrom_image_backend.h b/src/cdrom/cdrom_image_backend.h index b58b54d7b..69a59031c 100644 --- a/src/cdrom/cdrom_image_backend.h +++ b/src/cdrom/cdrom_image_backend.h @@ -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, * Fred N. van Kempen, * The DOSBox Team, * - * 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); diff --git a/src/chipset/acc2168.c b/src/chipset/acc2168.c index 1df0fec34..686301c24 100644 --- a/src/chipset/acc2168.c +++ b/src/chipset/acc2168.c @@ -20,19 +20,18 @@ #include #include #include -#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" diff --git a/src/chipset/acer_m3a.c b/src/chipset/acer_m3a.c index 0d8ab2052..43c19d6f1 100644 --- a/src/chipset/acer_m3a.c +++ b/src/chipset/acer_m3a.c @@ -20,13 +20,13 @@ #include #include #include -#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" diff --git a/src/chipset/ali1429.c b/src/chipset/ali1429.c index 5d5b4bd83..2f6b8cad1 100644 --- a/src/chipset/ali1429.c +++ b/src/chipset/ali1429.c @@ -21,19 +21,19 @@ #include #include #include -#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" diff --git a/src/chipset/chipset.h b/src/chipset/chipset.h index bf2cda160..9c9b96a2c 100644 --- a/src/chipset/chipset.h +++ b/src/chipset/chipset.h @@ -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, * - * 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; diff --git a/src/chipset/headland.c b/src/chipset/headland.c index cbd52cfb1..d3f1f4081 100644 --- a/src/chipset/headland.c +++ b/src/chipset/headland.c @@ -25,18 +25,18 @@ #include #include #include -#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" diff --git a/src/chipset/intel_4x0.c b/src/chipset/intel_4x0.c index cf2901146..3a711ba3d 100644 --- a/src/chipset/intel_4x0.c +++ b/src/chipset/intel_4x0.c @@ -8,48 +8,55 @@ * * Implementation of the Intel PCISet chips from 420TX to 440FX. * - * Version: @(#)intel_4x0.c 1.0.2 2019/10/21 + * Version: @(#)intel_4x0.c 1.0.3 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2019 Miran Grca. + * Copyright 2019,2020 Miran Grca. */ #include #include #include #include #include -#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 "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 "chipset.h" enum { INTEL_420TX, + INTEL_420ZX, INTEL_430LX, INTEL_430NX, INTEL_430FX, INTEL_430FX_PB640, INTEL_430HX, - INTEL_430VX + INTEL_430VX, + INTEL_430TX, #if defined(DEV_BRANCH) && defined(USE_I686) - ,INTEL_440FX -#endif + INTEL_440FX, +#endif + INTEL_440BX, + INTEL_440ZX }; typedef struct { - uint8_t regs[256]; + uint8_t pm2_cntrl, max_func; + uint8_t regs[2][256], regs_locked[2][256]; int type; } i4x0_t; + + static void i4x0_map(uint32_t addr, uint32_t size, int state) { @@ -71,116 +78,884 @@ i4x0_map(uint32_t addr, uint32_t size, int state) } +static void +i4x0_mask_bar(uint8_t *regs) +{ + uint32_t bar; + + bar = (regs[0x13] << 24) | (regs[0x12] << 16); + bar &= (((uint32_t) regs[0xb4] << 22) | 0xf0000000); + regs[0x12] = (bar >> 16) & 0xff; + regs[0x13] = (bar >> 24) & 0xff; +} + + +static uint8_t +pm2_cntrl_read(uint16_t addr, void *p) +{ + i4x0_t *dev = (i4x0_t *) p; + + return dev->pm2_cntrl & 0x01; +} + + +static void +pm2_cntrl_write(uint16_t addr, uint8_t val, void *p) +{ + i4x0_t *dev = (i4x0_t *) p; + + dev->pm2_cntrl = val & 0x01; +} + + static void i4x0_write(int func, int addr, uint8_t val, void *priv) { i4x0_t *dev = (i4x0_t *) priv; + uint8_t *regs = (uint8_t *) dev->regs[func]; + uint8_t *regs_l = (uint8_t *) dev->regs_locked[func]; + int i; - if (func) - return; + if (func > dev->max_func) + return; if ((addr >= 0x10) && (addr < 0x4f)) return; - switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0e: - return; - + if (func == 0) switch (addr) { case 0x04: /*Command register*/ - if (dev->type >= INTEL_430FX) { - if (dev->type == INTEL_430FX_PB640) - val &= 0x06; - else - val &= 0x02; - } else - val &= 0x42; - val |= 0x04; + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: + case INTEL_440BX: case INTEL_440ZX: + default: + regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42); + break; + case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02); + break; + } break; case 0x05: - if (dev->type >= INTEL_430FX) - val = 0; - else - val &= 0x01; - break; - - case 0x06: /*Status*/ - val = 0; + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[0x05] = (regs[0x05] & ~0x01) | (val & 0x01); + break; + } break; case 0x07: - if (dev->type >= INTEL_430HX) { - val &= 0x80; - val |= 0x02; - } else { - val = 0x02; - if (dev->type == INTEL_430FX_PB640) - val |= 0x20; + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: case INTEL_430HX: + default: + regs[0x07] &= ~(val & 0x70); + break; + case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430VX: case INTEL_430TX: + regs[0x07] &= ~(val & 0x30); + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x07] &= ~(val & 0xf9); + break; +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[0x07] &= ~(val & 0xf0); + break; } break; - - case 0x52: /*Cache Control Register*/ -#if defined(DEV_BRANCH) && defined(USE_I686) - if (dev->type < INTEL_440FX) { -#endif - cpu_cache_ext_enabled = (val & 0x01); - cpu_update_waitstates(); -#if defined(DEV_BRANCH) && defined(USE_I686) + case 0x0d: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: + regs[0x0d] = (val & 0xf0); + break; + default: + regs[0x0d] = (val & 0xf8); + break; } -#endif break; + case 0x0f: + switch (dev->type) { + case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX: + regs[0x0f] = (val & 0x40); + break; + } + break; + case 0x12: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x12] = (val & 0xc0); + i4x0_mask_bar(regs); + break; + } + break; + case 0x13: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x13] = val; + i4x0_mask_bar(regs); + break; + } + break; + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + if (!regs_l[addr]) { + regs[addr] = val; + regs_l[addr] = 1; + } + break; + } + break; + case 0x4f: + switch (dev->type) { + case INTEL_430HX: + regs[0x4f] = (val & 0x84); + break; + case INTEL_430VX: + regs[0x4f] = (val & 0x94); + break; + case INTEL_430TX: + regs[0x4f] = (val & 0x80); + break; + } + break; + case 0x50: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: default: + regs[0x50] = (val & 0xe5); + break; + case INTEL_430NX: + regs[0x50] = (val & 0xe7); + break; + case INTEL_430FX: case INTEL_430FX_PB640: + regs[0x50] = (val & 0xef); + break; + case INTEL_430HX: + regs[0x50] = (val & 0xf7); + break; + case INTEL_430VX: case INTEL_430TX: + regs[0x50] = (val & 0x08); + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x50] = (val & 0xf4); + break; +#endif + case INTEL_440BX: + regs[0x50] = (regs[0x50] & 0x14) | (val & 0xeb); + break; + case INTEL_440ZX: + regs[0x50] = (regs[0x50] & 0x34) | (val & 0xcb); + break; - case 0x59: /*PAM0*/ - if ((dev->regs[0x59] ^ val) & 0xf0) { + } + break; + case 0x51: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: + regs[0x51] = (val & 0xc0); + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x51] = (val & 0xc3); + break; +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[0x51] = (regs[0x50] & 0x70) | (val & 0x8f); + break; + } + break; + case 0x52: /* Cache Control Register */ + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: + case INTEL_430FX: case INTEL_430FX_PB640: + case INTEL_430VX: case INTEL_430TX: + default: + regs[0x52] = (val & 0xfb); + break; + case INTEL_430NX: case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + regs[0x52] = val; + break; + case INTEL_440BX: case INTEL_440ZX: + regs[0x52] = val & 0x07; + break; + } + break; + case 0x53: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: + regs[0x53] = val & 0x0b; + break; + case INTEL_430NX: + regs[0x53] = val & 0x0a; + break; + case INTEL_430VX: case INTEL_430TX: + regs[0x53] = val & 0x3f; + break; + case INTEL_440BX: + /* Not applicable to 440ZX as that does not support ECC. */ + regs[0x53] = val; + break; + } + break; + case 0x54: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + regs[0x54] = val & 0x07; + break; + case INTEL_430VX: + regs[0x54] = val & 0xd8; + break; + case INTEL_430TX: + regs[0x54] = val & 0xfa; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x54] = val & 0x82; + break; +#endif + } + break; + case 0x55: + switch (dev->type) { + case INTEL_430VX: case INTEL_430TX: + regs[0x55] = val & 0x01; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x55] = val; + break; +#endif + } + break; + case 0x56: + switch (dev->type) { + case INTEL_430HX: + regs[0x56] = val & 0x1f; + break; + case INTEL_430VX: + regs[0x56] = val & 0x77; + break; + case INTEL_430TX: + regs[0x56] = val & 0x76; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x56] = val; + break; +#endif + } + break; + case 0x57: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: default: + regs[0x57] = val & 0x3f; + break; + case INTEL_430NX: + regs[0x57] = val; + break; + case INTEL_430FX: case INTEL_430FX_PB640: + case INTEL_430HX: case INTEL_430VX: + regs[0x57] = val & 0xcf; + break; + case INTEL_430TX: + regs[0x57] = val & 0xdf; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x57] = val & 0x77; + break; +#endif + case INTEL_440BX: + regs[0x57] = val & 0x3f; + break; + case INTEL_440ZX: + regs[0x57] = val & 0x2f; + break; + } + break; + case 0x58: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: default: + regs[0x58] = val & 0x01; + break; + case INTEL_430NX: + case INTEL_440BX: case INTEL_440ZX: + regs[0x58] = val & 0x03; + break; + case INTEL_430FX: case INTEL_430FX_PB640: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + regs[0x58] = val & 0x7f; + break; + case INTEL_430HX: case INTEL_430VX: + regs[0x57] = val; + break; + case INTEL_430TX: + regs[0x57] = val & 0x7b; + break; + } + break; + case 0x59: /* PAM0 */ + if (dev->type <= INTEL_430NX) { + if ((regs[0x59] ^ val) & 0x0f) + i4x0_map(0x80000, 0x20000, val & 0x0f); + } + if ((regs[0x59] ^ val) & 0xf0) { i4x0_map(0xf0000, 0x10000, val >> 4); shadowbios = (val & 0x10); } + if (dev->type > INTEL_430NX) + regs[0x59] = val & 0x70; + else + regs[0x59] = val & 0x77; break; - case 0x5a: /*PAM1*/ - if ((dev->regs[0x5a] ^ val) & 0x0f) + case 0x5a: /* PAM1 */ + if ((regs[0x5a] ^ val) & 0x0f) i4x0_map(0xc0000, 0x04000, val & 0xf); - if ((dev->regs[0x5a] ^ val) & 0xf0) + if ((regs[0x5a] ^ val) & 0xf0) i4x0_map(0xc4000, 0x04000, val >> 4); + regs[0x5a] = val & 0x77; break; - case 0x5b: /*PAM2*/ - if ((dev->regs[0x5b] ^ val) & 0x0f) + case 0x5b: /*PAM2 */ + if ((regs[0x5b] ^ val) & 0x0f) i4x0_map(0xc8000, 0x04000, val & 0xf); - if ((dev->regs[0x5b] ^ val) & 0xf0) + if ((regs[0x5b] ^ val) & 0xf0) i4x0_map(0xcc000, 0x04000, val >> 4); + regs[0x5b] = val & 0x77; break; - case 0x5c: /*PAM3*/ - if ((dev->regs[0x5c] ^ val) & 0x0f) + case 0x5c: /*PAM3 */ + if ((regs[0x5c] ^ val) & 0x0f) i4x0_map(0xd0000, 0x04000, val & 0xf); - if ((dev->regs[0x5c] ^ val) & 0xf0) + if ((regs[0x5c] ^ val) & 0xf0) i4x0_map(0xd4000, 0x04000, val >> 4); + regs[0x5c] = val & 0x77; break; - case 0x5d: /*PAM4*/ - if ((dev->regs[0x5d] ^ val) & 0x0f) + case 0x5d: /* PAM4 */ + if ((regs[0x5d] ^ val) & 0x0f) i4x0_map(0xd8000, 0x04000, val & 0xf); - if ((dev->regs[0x5d] ^ val) & 0xf0) + if ((regs[0x5d] ^ val) & 0xf0) i4x0_map(0xdc000, 0x04000, val >> 4); + regs[0x5d] = val & 0x77; break; - case 0x5e: /*PAM5*/ - if ((dev->regs[0x5e] ^ val) & 0x0f) + case 0x5e: /* PAM5 */ + if ((regs[0x5e] ^ val) & 0x0f) i4x0_map(0xe0000, 0x04000, val & 0xf); - if ((dev->regs[0x5e] ^ val) & 0xf0) + if ((regs[0x5e] ^ val) & 0xf0) i4x0_map(0xe4000, 0x04000, val >> 4); + regs[0x5e] = val & 0x77; break; - case 0x5f: /*PAM6*/ - if ((dev->regs[0x5f] ^ val) & 0x0f) + case 0x5f: /* PAM6 */ + if ((regs[0x5f] ^ val) & 0x0f) i4x0_map(0xe8000, 0x04000, val & 0xf); - if ((dev->regs[0x5f] ^ val) & 0xf0) + if ((regs[0x5f] ^ val) & 0xf0) i4x0_map(0xec000, 0x04000, val >> 4); + regs[0x5f] = val & 0x77; break; - case 0x72: /*SMRAM*/ - if ((dev->type >= INTEL_430FX) && ((dev->regs[0x72] ^ val) & 0x48)) - i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); - else if ((dev->type < INTEL_430FX) && ((dev->regs[0x72] ^ val) & 0x20)) - i4x0_map(0xa0000, 0x20000, ((val & 0x20) == 0x20) ? 3 : 0); + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + case INTEL_440BX: case INTEL_440ZX: + default: + regs[addr] = val; + break; + case INTEL_430FX: case INTEL_430FX_PB640: + case INTEL_430VX: + regs[addr] = val/* & 0x3f*/; + break; + case INTEL_430TX: + regs[addr] = val & 0x7f; + break; + } + break; + case 0x65: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + break; + case INTEL_430VX: + regs[addr] = val & 0x3f; + break; + case INTEL_430TX: + regs[addr] = val & 0x7f; + break; + } + break; + case 0x66: + switch (dev->type) { + case INTEL_430NX: case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + break; + } + break; + case 0x67: + switch (dev->type) { + case INTEL_430NX: case INTEL_430HX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + break; + case INTEL_430VX: + regs[addr] = val & 0x11; + break; + case INTEL_430TX: + regs[addr] = val & 0xb7; + break; + } + break; + case 0x68: + switch (dev->type) { + case INTEL_430NX: case INTEL_430HX: + case INTEL_430VX: case INTEL_430TX: + regs[0x68] = val; + break; + case INTEL_430FX: case INTEL_430FX_PB640: + regs[0x68] = val & 0x1f; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x68] = val & 0xc0; + break; +#endif + case INTEL_440BX: + regs[0x68] = (regs[0x68] & 0x38) | (val & 0xc7); + break; + case INTEL_440ZX: + regs[0x68] = (regs[0x68] & 0x3f) | (val & 0xc0); + break; + } + break; + case 0x69: + switch (dev->type) { + case INTEL_430NX: + case INTEL_440BX: + regs[0x69] = val; + break; + case INTEL_430VX: + regs[0x69] = val & 0x07; + break; + case INTEL_440ZX: + regs[0x69] = val & 0x3f; + break; + } + break; + case 0x6a: case 0x6b: + switch (dev->type) { + case INTEL_430NX: + case INTEL_440BX: + regs[addr] = val; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440ZX: + if (addr == 0x6a) + regs[addr] = val & 0xfc; + else + regs[addr] = val & 0x33; + break; +#endif + } + break; + case 0x6c: case 0x6d: case 0x6e: + switch (dev->type) { + case INTEL_440BX: + regs[addr] = val; + break; + case INTEL_440ZX: + if (addr == 0x6c) + regs[addr] = val & 0x03; + else if (addr == 0x6d) + regs[addr] = val & 0xcf; + break; + } + break; + case 0x70: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: + regs[addr] = val & 0xc7; + break; + case INTEL_430NX: + regs[addr] = val; + break; + case INTEL_430VX: case INTEL_430TX: + regs[addr] = val & 0xfc; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[addr] = val & 0xf8; + break; +#endif + } + break; + case 0x71: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: + regs[addr] = val & 0x4d; + break; + case INTEL_430TX: + regs[addr] = val; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[addr] = val & 0x1f; + break; +#endif + } + break; + case 0x72: /* SMRAM */ + if (dev->type >= INTEL_430FX) { + if ((regs[0x72] ^ val) & 0x48) + i4x0_map(0xa0000, 0x20000, ((val & 0x48) == 0x48) ? 3 : 0); + regs[0x72] = val & 0x7f; + } else { + if ((regs[0x72] ^ val) & 0x20) + i4x0_map(0xa0000, 0x20000, ((val & 0x20) == 0x20) ? 3 : 0); + regs[0x72] = val & 0x3f; + } + break; + case 0x73: + switch (dev->type) { + case INTEL_430VX: + regs[0x73] = val & 0x03; + break; + case INTEL_440BX: case INTEL_440ZX: + regs[0x73] = val; + break; + } + break; + case 0x74: + switch (dev->type) { + case INTEL_430VX: + case INTEL_440BX: case INTEL_440ZX: + regs[0x74] = val; + break; + } + break; + case 0x75: case 0x76: + case 0x7b: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + } + break; + case 0x77: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x77] = val & 0x03; + } + break; + case 0x78: + switch (dev->type) { + case INTEL_430VX: + regs[0x78] = val & 0xcf; + break; + case INTEL_440BX: case INTEL_440ZX: + regs[0x78] = val & 0x0f; + break; + } + break; + case 0x79: + switch (dev->type) { + case INTEL_430TX: + regs[0x79] = val & 0x74; + io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + if (val & 0x40) + io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + break; + case INTEL_440BX: case INTEL_440ZX: + regs[0x79] = val; + break; + } + break; + case 0x7a: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x7a] = (regs[0x7a] & 0x0a) | (val & 0xf5); + io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + if (val & 0x40) + io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + break; + } + break; + case 0x7c: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + regs[0x7c] = val & 0x8f; + break; + case INTEL_440BX: case INTEL_440ZX: + regs[0x7c] = val & 0x1f; + break; + } + case 0x7d: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + regs[0x7c] = val & 0x32; + break; + } + case 0x7e: case 0x7f: + switch (dev->type) { + case INTEL_420TX: case INTEL_420ZX: + case INTEL_430LX: case INTEL_430NX: + regs[addr] = val; + break; + } + case 0x80: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x80] &= ~(val & 0x03); + break; + } + break; + case 0x90: + switch (dev->type) { + case INTEL_430HX: + regs[0x80] = val & 0x87; + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: + regs[0x80] = val & 0x1b; + break; +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[0x7c] = val; + break; + } + break; + case 0x91: + switch (dev->type) { + case INTEL_430HX: case INTEL_440BX: +#if defined(DEV_BRANCH) && defined(USE_I686) + case INTEL_440FX: +#endif + /* Not applicable on 82443ZX. */ + regs[0x91] &= ~(val & 0x11); + break; + } + break; + case 0x92: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x92] &= ~(val & 0x1f); + break; + } + break; +#if defined(DEV_BRANCH) && defined(USE_I686) + case 0x93: + switch (dev->type) { + case INTEL_440FX: + regs[0x93] = (val & 0x0f); + trc_write(0x0093, val & 0x06, NULL); + break; + } + break; +#endif + case 0xa8: case 0xa9: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = (val & 0x03); + break; + } + break; + case 0xb0: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xb0] = (val & 0x80); + break; + } + break; + case 0xb1: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xb1] = (val & 0xa0); + break; + } + break; + case 0xb4: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xb4] = (val & 0x3f); + i4x0_mask_bar(regs); + break; + } + break; + case 0xb9: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xb9] = (val & 0xf0); + break; + } + break; + case 0xba: case 0xbb: + case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + break; + } + break; + case 0xca: + switch (dev->type) { + case INTEL_440BX: + regs[addr] = val; + break; + case INTEL_440ZX: + regs[addr] = val & 0xe7; + break; + } + break; + case 0xcb: + switch (dev->type) { + case INTEL_440BX: + regs[addr] = val; + break; + case INTEL_440ZX: + regs[addr] = val & 0xa7; + break; + } + break; + case 0xcc: + switch (dev->type) { + case INTEL_440BX: + regs[0xcc] = (val & 0x7f); + break; + case INTEL_440ZX: + regs[0xcc] = (val & 0x58); + break; + } + break; + case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: + case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + if (!regs_l[addr]) + regs[addr] = val; + break; + } + break; + case 0xe5: case 0xed: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + if (!regs_l[addr]) + regs[addr] = (val & 0x3f); + break; + } + break; + case 0xe7: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xe7] = 0x80; + for (i = 0; i < 16; i++) + regs_l[0xe0 + i] = !!(val & 0x80); + if (!regs_l[0xe7]) { + regs[0xe7] |= (val & 0x7f); + } + break; + } + break; + case 0xf0: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xf0] = (val & 0xc0); + break; + } + break; + case 0xf1: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0xf1] = (val & 0x03); + break; + } + break; + } else if (func == 1) switch (addr) { + case 0x04: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x04] = (val & 0x1f); + break; + } + break; + case 0x05: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x05] = (val & 0x01); + break; + } + break; + case 0x0d: case 0x1b: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = (val & 0xf8); + break; + } + break; + case 0x19: case 0x1a: + case 0x21: case 0x23: + case 0x25: case 0x27: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = val; + break; + } + break; + case 0x1c: case 0x1d: + case 0x20: case 0x22: + case 0x24: case 0x26: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[addr] = (val & 0xf0); + break; + } + break; + case 0x1f: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x1f] &= ~(val & 0xf0); + break; + } + break; + case 0x3e: + switch (dev->type) { + case INTEL_440BX: case INTEL_440ZX: + regs[0x3e] = (val & 0xed); + break; + } break; } - - dev->regs[addr] = val; } @@ -188,22 +963,50 @@ static uint8_t i4x0_read(int func, int addr, void *priv) { i4x0_t *dev = (i4x0_t *) priv; + uint8_t ret = 0xff; + uint8_t *regs = (uint8_t *) dev->regs[func]; - if (func) - return 0xff; + if (func > dev->max_func) + ret = 0xff; + else { + ret = regs[addr]; +#if defined(DEV_BRANCH) && defined(USE_I686) + /* Special behavior for 440FX register 0x93 which is basically TRC in PCI space + with the addition of bits 3 and 0. */ + if ((func == 0) && (addr == 0x93) && (dev->type == INTEL_440FX)) + ret = (ret & 0xf9) | (trc_read(0x0093, NULL) & 0x06); +#endif + } - return dev->regs[addr]; + return ret; } static void i4x0_reset(void *priv) { - i4x0_t *i4x0 = (i4x0_t *)priv; + i4x0_t *dev = (i4x0_t *)priv; + int i; - i4x0_write(0, 0x59, 0x00, priv); - if (i4x0->type >= INTEL_430FX) + if (dev->type >= INTEL_430FX) + i4x0_write(0, 0x59, 0x00, priv); + else + i4x0_write(0, 0x59, 0x0f, priv); + + for (i = 0; i < 6; i++) + i4x0_write(0, 0x5a + i, 0x00, priv); + + if (dev->type >= INTEL_430FX) i4x0_write(0, 0x72, 0x02, priv); + else + i4x0_write(0, 0x72, 0x00, priv); + + if ((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) { + for (i = 0; i <= dev->max_func; i++) + memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t)); + } + + smbase = 0xa0000; } @@ -219,114 +1022,227 @@ i4x0_close(void *p) static void *i4x0_init(const device_t *info) { - i4x0_t *i4x0 = (i4x0_t *) malloc(sizeof(i4x0_t)); - memset(i4x0, 0, sizeof(i4x0_t)); + i4x0_t *dev = (i4x0_t *) malloc(sizeof(i4x0_t)); + uint8_t *regs; - i4x0->type = info->local; + memset(dev, 0, sizeof(i4x0_t)); - i4x0->regs[0x00] = 0x86; i4x0->regs[0x01] = 0x80; /*Intel*/ - switch(i4x0->type) { + dev->type = info->local & 0xff; + + regs = (uint8_t *) dev->regs[0]; + + // This is off by default and has to be moved to the appropriate register handling. + // io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev); + + regs[0x00] = 0x86; regs[0x01] = 0x80; /*Intel*/ + + switch (dev->type) { case INTEL_420TX: - i4x0->regs[0x02] = 0x83; i4x0->regs[0x03] = 0x04; /*82424TX/ZX*/ - i4x0->regs[0x08] = 0x03; /*A3 stepping*/ - i4x0->regs[0x50] = 0x80; - i4x0->regs[0x52] = 0x40; /*256kb PLB cache*/ + case INTEL_420ZX: + regs[0x02] = 0x83; regs[0x03] = 0x04; /* 82424TX/ZX */ + regs[0x06] = 0x40; + regs[0x08] = (dev->type == INTEL_420ZX) ? 0x01 : 0x00; + regs[0x0d] = 0x20; + if (is486sx) + regs[0x50] = 0x20; + else if (is486sx2) + regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */ + else if (is486dx || isdx4) + regs[0x50] = 0x00; + else if (is486dx2) + regs[0x50] = 0x40; + else + regs[0x50] = 0x80; /* Pentium OverDrive. */ + if (cpu_busspeed <= 25000000) + regs[0x50] |= 0x01; + else if ((cpu_busspeed > 25000000) && (cpu_busspeed <= 30000000)) + regs[0x50] |= 0x02; + else if ((cpu_busspeed > 30000000) && (cpu_busspeed <= 33333333)) + regs[0x50] |= 0x03; + regs[0x51] = 0x80; + regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ + regs[0x57] = 0x31; + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; break; case INTEL_430LX: - i4x0->regs[0x02] = 0xa3; i4x0->regs[0x03] = 0x04; /*82434LX/NX*/ - i4x0->regs[0x08] = 0x03; /*A3 stepping*/ - i4x0->regs[0x50] = 0x80; - i4x0->regs[0x52] = 0x40; /*256kb PLB cache*/ + regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ + regs[0x06] = 0x40; + regs[0x08] = 0x03; + regs[0x0d] = 0x20; + regs[0x50] = 0x82; + if (cpu_busspeed <= 60000000) + regs[0x50] |= 0x00; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x50] |= 0x01; + regs[0x51] = 0x80; + regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ + regs[0x57] = 0x31; + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; break; case INTEL_430NX: - i4x0->regs[0x02] = 0xa3; i4x0->regs[0x03] = 0x04; /*82434LX/NX*/ - i4x0->regs[0x08] = 0x10; /*A0 stepping*/ - i4x0->regs[0x50] = 0xA0; - i4x0->regs[0x52] = 0x44; /*256kb PLB cache*/ - i4x0->regs[0x66] = i4x0->regs[0x67] = 0x02; + regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */ + regs[0x06] = 0x40; + regs[0x08] = 0x11; + regs[0x0d] = 0x20; + regs[0x50] = 0x80; + if (cpu_busspeed <= 50000000) + regs[0x50] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x50] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x50] |= 0x03; + regs[0x51] = 0x80; + regs[0x52] = 0xea; /* 512 kB burst cache, set to 0xaa for 256 kB */ + regs[0x57] = 0x31; + regs[0x59] = 0x0f; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; break; - case INTEL_430FX: case INTEL_430FX_PB640: - i4x0->regs[0x02] = 0x2d; i4x0->regs[0x03] = 0x12; /*SB82437FX-66*/ - if (i4x0->type == INTEL_430FX_PB640) - i4x0->regs[0x08] = 0x02; /*???? stepping*/ - else - i4x0->regs[0x08] = 0x00; /*A0 stepping*/ - i4x0->regs[0x52] = 0x40; /*256kb PLB cache*/ + regs[0x08] = 0x02; + /* FALLTHROUGH */ + case INTEL_430FX: + regs[0x02] = 0x2d; regs[0x03] = 0x12; /* SB82437FX-66 */ + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; + regs[0x72] = 0x02; break; case INTEL_430HX: - i4x0->regs[0x02] = 0x50; i4x0->regs[0x03] = 0x12; /*82439HX*/ - i4x0->regs[0x08] = 0x00; /*A0 stepping*/ - i4x0->regs[0x51] = 0x20; - i4x0->regs[0x52] = 0xB5; /*512kb cache*/ - i4x0->regs[0x56] = 0x52; /*DRAM control*/ - i4x0->regs[0x59] = 0x40; - i4x0->regs[0x5A] = i4x0->regs[0x5B] = i4x0->regs[0x5C] = i4x0->regs[0x5D] = 0x44; - i4x0->regs[0x5E] = i4x0->regs[0x5F] = 0x44; - i4x0->regs[0x65] = i4x0->regs[0x66] = i4x0->regs[0x67] = 0x02; - i4x0->regs[0x68] = 0x11; + regs[0x02] = 0x50; regs[0x03] = 0x12; /* 82439HX */ + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; + regs[0x72] = 0x02; break; case INTEL_430VX: - i4x0->regs[0x02] = 0x30; i4x0->regs[0x03] = 0x70; /*82437VX*/ - i4x0->regs[0x08] = 0x00; /*A0 stepping*/ - i4x0->regs[0x52] = 0x42; /*256kb PLB cache*/ - i4x0->regs[0x53] = 0x14; - i4x0->regs[0x56] = 0x52; /*DRAM control*/ - i4x0->regs[0x67] = 0x11; - i4x0->regs[0x69] = 0x03; - i4x0->regs[0x70] = 0x20; - i4x0->regs[0x74] = 0x0e; - i4x0->regs[0x78] = 0x23; + regs[0x02] = 0x30; regs[0x03] = 0x70; /* 82437VX */ + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + regs[0x53] = 0x14; + regs[0x56] = 0x52; + if (cpu_busspeed <= 50000000) + regs[0x57] |= 0x01; + else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000)) + regs[0x57] |= 0x02; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x57] |= 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02; + regs[0x67] = 0x11; + regs[0x69] = 0x03; + regs[0x70] = 0x20; + regs[0x72] = 0x02; + regs[0x74] = 0x0e; + regs[0x78] = 0x23; + break; + case INTEL_430TX: + regs[0x02] = 0x00; regs[0x03] = 0x71; /* 82439TX */ + regs[0x08] = 0x01; + regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */ + regs[0x53] = 0x14; + regs[0x56] = 0x52; + regs[0x57] = 0x01; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02; + if (cpu_busspeed <= 60000000) + regs[0x67] |= 0x00; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x67] |= 0x80; + regs[0x70] = 0x20; + regs[0x72] = 0x02; break; #if defined(DEV_BRANCH) && defined(USE_I686) case INTEL_440FX: - i4x0->regs[0x02] = 0x37; i4x0->regs[0x03] = 0x12; /*82441FX*/ - i4x0->regs[0x08] = 0x02; /*A0 stepping*/ - i4x0->regs[0x2c] = 0xf4; - i4x0->regs[0x2d] = 0x1a; - i4x0->regs[0x2f] = 0x11; - i4x0->regs[0x51] = 0x01; - i4x0->regs[0x53] = 0x80; - i4x0->regs[0x58] = 0x10; - i4x0->regs[0x5a] = i4x0->regs[0x5b] = i4x0->regs[0x5c] = i4x0->regs[0x5d] = 0x11; - i4x0->regs[0x5e] = 0x11; - i4x0->regs[0x5f] = 0x31; + regs[0x02] = 0x37; regs[0x03] = 0x12; /* 82441FX */ + regs[0x08] = 0x02; + if (cpu_busspeed <= 60000000) + regs[0x51] |= 0x01; + else if ((cpu_busspeed > 60000000) && (cpu_busspeed <= 66666667)) + regs[0x51] |= 0x02; + regs[0x53] = 0x80; + regs[0x57] = 0x01; + regs[0x58] = 0x10; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02; + regs[0x71] = 0x10; + regs[0x72] = 0x02; + break; +#endif + case INTEL_440BX: case INTEL_440ZX: + regs[0x7a] = (info->local >> 8) & 0xff; + dev->max_func = (regs[0x7a] & 0x02) ? 0 : 1; + + regs[0x02] = (regs[0x7a] & 0x02) ? 0x92 : 0x90; regs[0x03] = 0x71; /* 82443BX */ + regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0x08] = 0x02; + regs[0x10] = 0x08; + regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0; + if (cpu_busspeed <= 66666667) + regs[0x51] |= 0x00; + else if ((cpu_busspeed > 66666667) && (cpu_busspeed <= 100000000)) + regs[0x51] |= 0x20; + regs[0x57] = 0x28; /* 4 DIMMs, SDRAM */ + regs[0x58] = 0x03; + regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01; + regs[0x72] = 0x02; + regs[0x73] = 0x38; + regs[0x7b] = 0x38; + regs[0x90] = 0x80; + regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02; + regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10; + regs[0xa4] = 0x03; + regs[0xa5] = 0x02; + regs[0xa7] = 0x1f; break; -#endif } - i4x0->regs[0x04] = 0x06; i4x0->regs[0x05] = 0x00; -#if defined(DEV_BRANCH) && defined(USE_I686) - if (i4x0->type == INTEL_440FX) - i4x0->regs[0x06] = 0x80; -#endif - if (i4x0->type == INTEL_430FX) - i4x0->regs[0x07] = 0x82; -#if defined(DEV_BRANCH) && defined(USE_I686) - else if (i4x0->type != INTEL_440FX) -#else - else -#endif - i4x0->regs[0x07] = 0x02; - i4x0->regs[0x0b] = 0x06; - if (i4x0->type >= INTEL_430FX) - i4x0->regs[0x57] = 0x01; - else - i4x0->regs[0x57] = 0x31; - i4x0->regs[0x60] = i4x0->regs[0x61] = i4x0->regs[0x62] = i4x0->regs[0x63] = 0x02; - i4x0->regs[0x64] = 0x02; - if (i4x0->type >= INTEL_430FX) - i4x0->regs[0x72] = 0x02; + + regs[0x04] = 0x06; regs[0x07] = 0x02; + regs[0x0b] = 0x06; #if defined(DEV_BRANCH) && defined(USE_I686) - if (i4x0->type == INTEL_440FX) { + if (dev->type >= INTEL_440FX) { cpu_cache_ext_enabled = 1; cpu_update_waitstates(); } #endif - pci_add_card(0, i4x0_read, i4x0_write, i4x0); + i4x0_write(regs[0x59], 0x59, 0x00, dev); + i4x0_write(regs[0x5a], 0x5a, 0x00, dev); + i4x0_write(regs[0x5b], 0x5b, 0x00, dev); + i4x0_write(regs[0x5c], 0x5c, 0x00, dev); + i4x0_write(regs[0x5d], 0x5d, 0x00, dev); + i4x0_write(regs[0x5e], 0x5e, 0x00, dev); + i4x0_write(regs[0x5f], 0x5f, 0x00, dev); - return i4x0; + smbase = 0xa0000; + + if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) { + regs = (uint8_t *) dev->regs[1]; + + regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */ + regs[0x02] = 0x91; regs[0x03] = 0x71; /* 82443BX */ + regs[0x06] = 0x20; regs[0x07] = 0x02; + regs[0x08] = 0x02; + regs[0x0a] = 0x04; regs[0x0b] = 0x06; + regs[0x0e] = 0x01; + regs[0x1c] = 0xf0; + regs[0x1e] = 0xa0; regs[0x1f] = 0x02; + regs[0x20] = 0xf0; regs[0x21] = 0xff; + regs[0x24] = 0xf0; regs[0x25] = 0xff; + regs[0x3e] = 0x80; + } + + pci_add_card(PCI_ADD_NORTHBRIDGE, i4x0_read, i4x0_write, dev); + + return dev; } @@ -345,6 +1261,21 @@ const device_t i420tx_device = }; +const device_t i420zx_device = +{ + "Intel 82424ZX", + DEVICE_PCI, + INTEL_420ZX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + const device_t i430lx_device = { "Intel 82434LX", @@ -435,6 +1366,21 @@ const device_t i430vx_device = }; +const device_t i430tx_device = +{ + "Intel 82439TX", + DEVICE_PCI, + INTEL_430TX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + #if defined(DEV_BRANCH) && defined(USE_I686) const device_t i440fx_device = { @@ -449,4 +1395,33 @@ const device_t i440fx_device = NULL, NULL }; + #endif +const device_t i440bx_device = +{ + "Intel 82443BX", + DEVICE_PCI, + 0x8000 | INTEL_440BX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; + + +const device_t i440zx_device = +{ + "Intel 82443ZX", + DEVICE_PCI, + 0x8000 | INTEL_440ZX, + i4x0_init, + i4x0_close, + i4x0_reset, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/chipset/neat.c b/src/chipset/neat.c index 4f2524db9..dc2798813 100644 --- a/src/chipset/neat.c +++ b/src/chipset/neat.c @@ -24,15 +24,15 @@ #include #include #include -#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 diff --git a/src/chipset/opti495.c b/src/chipset/opti495.c index b6ffb0ff8..21fa9f048 100644 --- a/src/chipset/opti495.c +++ b/src/chipset/opti495.c @@ -258,15 +258,15 @@ SeeAlso: #P0178,#P0187 #include #include #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" diff --git a/src/chipset/scamp.c b/src/chipset/scamp.c new file mode 100644 index 000000000..c6f3619c3 --- /dev/null +++ b/src/chipset/scamp.c @@ -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, + * + * Copyright 2020 Sarah Walker. + */ +#include +#include +#include +#include +#include +#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 +}; \ No newline at end of file diff --git a/src/chipset/scat.c b/src/chipset/scat.c index 0c3223486..a9b668141 100644 --- a/src/chipset/scat.c +++ b/src/chipset/scat.c @@ -23,24 +23,19 @@ #include #include #include -#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; } diff --git a/src/chipset/sis_85c471.c b/src/chipset/sis_85c471.c index 934e84c55..d28d824c1 100644 --- a/src/chipset/sis_85c471.c +++ b/src/chipset/sis_85c471.c @@ -22,20 +22,20 @@ #include #include #include -#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" diff --git a/src/chipset/sis_85c496.c b/src/chipset/sis_85c496.c index cddb74b9d..607178fb9 100644 --- a/src/chipset/sis_85c496.c +++ b/src/chipset/sis_85c496.c @@ -21,18 +21,18 @@ #include #include #include -#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); diff --git a/src/chipset/sis_85c50x.c b/src/chipset/sis_85c50x.c index f5a67198d..605799e17 100644 --- a/src/chipset/sis_85c50x.c +++ b/src/chipset/sis_85c50x.c @@ -20,14 +20,14 @@ #include #include #include -#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" diff --git a/src/chipset/via_mvp3.c b/src/chipset/via_mvp3.c new file mode 100644 index 000000000..cdbcc17d1 --- /dev/null +++ b/src/chipset/via_mvp3.c @@ -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, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2020 Miran Grca, Melissa Goad. + */ +#include +#include +#include +#include +#include +#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 +}; diff --git a/src/chipset/wd76c10.c b/src/chipset/wd76c10.c index e469f6672..f01290e65 100644 --- a/src/chipset/wd76c10.c +++ b/src/chipset/wd76c10.c @@ -23,17 +23,17 @@ #include #include #include -#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" diff --git a/src/config.c b/src/config.c index 2b9026989..6daa573aa 100644 --- a/src/config.c +++ b/src/config.c @@ -34,7 +34,7 @@ #include #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; cdata, "%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); } diff --git a/src/cpu/386.c b/src/cpu/386.c deleted file mode 100644 index 7694a0be4..000000000 --- a/src/cpu/386.c +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#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(); - } -} diff --git a/src/cpu/386_ops.h b/src/cpu/386_ops.h deleted file mode 100644 index fa2ed4d83..000000000 --- a/src/cpu/386_ops.h +++ /dev/null @@ -1,1647 +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. - * - * 286/386+ instruction handlers list. - * - * Version: @(#)386_ops.h 1.0.5 2018/10/17 - * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * leilei, - * Miran Grca, - * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * 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. - */ -#include "x86_ops.h" - - -#define ILLEGAL_ON(cond) \ - do \ - { \ - if ((cond)) \ - { \ - cpu_state.pc = cpu_state.oldpc; \ - x86illegal(); \ - return 0; \ - } \ - } while (0) - -static __inline void PUSH_W(uint16_t val) -{ - if (stack32) - { - writememw(ss, ESP - 2, val); if (cpu_state.abrt) return; - ESP -= 2; - cpu_state.last_ea = ESP; - } - else - { - writememw(ss, (SP - 2) & 0xFFFF, val); if (cpu_state.abrt) return; - SP -= 2; - cpu_state.last_ea = SP; - } -} - -static __inline void PUSH_L(uint32_t val) -{ - if (stack32) - { - writememl(ss, ESP - 4, val); if (cpu_state.abrt) return; - ESP -= 4; - cpu_state.last_ea = ESP; - } - else - { - writememl(ss, (SP - 4) & 0xFFFF, val); if (cpu_state.abrt) return; - SP -= 4; - cpu_state.last_ea = SP; - } -} - -static __inline uint16_t POP_W() -{ - uint16_t ret; - if (stack32) - { - ret = readmemw(ss, ESP); if (cpu_state.abrt) return 0; - ESP += 2; - cpu_state.last_ea = ESP; - } - else - { - ret = readmemw(ss, SP); if (cpu_state.abrt) return 0; - SP += 2; - cpu_state.last_ea = SP; - } - return ret; -} - -static __inline uint32_t POP_L() -{ - uint32_t ret; - if (stack32) - { - ret = readmeml(ss, ESP); if (cpu_state.abrt) return 0; - ESP += 4; - cpu_state.last_ea = ESP; - } - else - { - ret = readmeml(ss, SP); if (cpu_state.abrt) return 0; - SP += 4; - cpu_state.last_ea = SP; - } - return ret; -} - -static __inline uint16_t POP_W_seg(uint32_t seg) -{ - uint16_t ret; - if (stack32) - { - ret = readmemw(seg, ESP); if (cpu_state.abrt) return 0; - ESP += 2; - cpu_state.last_ea = ESP; - } - else - { - ret = readmemw(seg, SP); if (cpu_state.abrt) return 0; - SP += 2; - cpu_state.last_ea = SP; - } - return ret; -} - -static __inline uint32_t POP_L_seg(uint32_t seg) -{ - uint32_t ret; - if (stack32) - { - ret = readmeml(seg, ESP); if (cpu_state.abrt) return 0; - ESP += 4; - cpu_state.last_ea = ESP; - } - else - { - ret = readmeml(seg, SP); if (cpu_state.abrt) return 0; - SP += 4; - cpu_state.last_ea = SP; - } - return ret; -} - -static int fopcode; - -static int ILLEGAL(uint32_t fetchdat) -{ - cpu_state.pc = cpu_state.oldpc; - - pclog("Illegal instruction %08X (%02X)\n", fetchdat, fopcode); - x86illegal(); - return 0; -} - -#if 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, ...); -#else -#ifndef x386_dynarec_log -#define x386_dynarec_log(fmt, ...) -#endif -#endif - -#include "x86seg.h" -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -# include "x86_ops_amd.h" -#endif -#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" -#include "x86_ops_int.h" -#include "x86_ops_io.h" -#include "x86_ops_jump.h" -#include "x86_ops_misc.h" -#include "x87_ops.h" -#if defined(DEV_BRANCH) && defined(USE_I686) -# include "x86_ops_i686.h" -#endif -#include "x86_ops_mmx.h" -#include "x86_ops_mmx_arith.h" -#include "x86_ops_mmx_cmp.h" -#include "x86_ops_mmx_logic.h" -#include "x86_ops_mmx_mov.h" -#include "x86_ops_mmx_pack.h" -#include "x86_ops_mmx_shift.h" -#include "x86_ops_mov.h" -#include "x86_ops_mov_ctrl.h" -#include "x86_ops_mov_seg.h" -#include "x86_ops_movx.h" -#include "x86_ops_msr.h" -#include "x86_ops_mul.h" -#include "x86_ops_pmode.h" -#include "x86_ops_prefix.h" -#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" - - -static int op0F_w_a16(uint32_t fetchdat) -{ - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); - - return x86_opcodes_0f[opcode](fetchdat >> 8); -} -static int op0F_l_a16(uint32_t fetchdat) -{ - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); - - return x86_opcodes_0f[opcode | 0x100](fetchdat >> 8); -} -static int op0F_w_a32(uint32_t fetchdat) -{ - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); - - return x86_opcodes_0f[opcode | 0x200](fetchdat >> 8); -} -static int op0F_l_a32(uint32_t fetchdat) -{ - int opcode = fetchdat & 0xff; - fopcode = opcode; - cpu_state.pc++; - - PREFETCH_PREFIX(); - - return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8); -} - - -const OpFn OP_TABLE(286_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_286, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opLOADALL, opCLTS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*90*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*a0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*b0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -}; - -const OpFn OP_TABLE(386_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -}; - -const OpFn OP_TABLE(486_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -}; - -const OpFn OP_TABLE(winchip_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, -}; - -const OpFn OP_TABLE(pentium_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -}; - -const OpFn OP_TABLE(pentiummmx_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, -}; - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -const OpFn OP_TABLE(k6_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, opSYSCALL, opCLTS, opSYSRET, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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(DEV_BRANCH) && defined(USE_CYRIX_6X86) -const OpFn OP_TABLE(c6x86mx_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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 -const OpFn OP_TABLE(pentiumpro_0f)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*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*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,opFXSAVESTOR_a16,opIMUL_w_w_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, - -/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,opFXSAVESTOR_a16,opIMUL_l_l_a16, -/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, - -/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, -/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, -/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,opFXSAVESTOR_a32,opIMUL_w_w_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, - -/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opNOP, ILLEGAL, ILLEGAL, -/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, - -/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, -/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, - -/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, -/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,opFXSAVESTOR_a32,opIMUL_l_l_a32, -/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, - -/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, -/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, -/*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 -#endif - -const OpFn OP_TABLE(286)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, -/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, -/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, -/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, -/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, -/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, -/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, -/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF_286, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, -/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, -}; - -const OpFn OP_TABLE(386)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_w_rmw_a16,opADD_b_rm_a16, opADD_w_rm_a16, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a16, opOR_w_rmw_a16, opOR_b_rm_a16, opOR_w_rm_a16, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a16, -/*10*/ opADC_b_rmw_a16,opADC_w_rmw_a16,opADC_b_rm_a16, opADC_w_rm_a16, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a16,opSBB_w_rmw_a16,opSBB_b_rm_a16, opSBB_w_rm_a16, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a16,opAND_w_rmw_a16,opAND_b_rm_a16, opAND_w_rm_a16, opAND_AL_imm, opAND_AX_imm, opES_w_a16, opDAA, opSUB_b_rmw_a16,opSUB_w_rmw_a16,opSUB_b_rm_a16, opSUB_w_rm_a16, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_w_rmw_a16,opXOR_b_rm_a16, opXOR_w_rm_a16, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a16, opAAA, opCMP_b_rmw_a16,opCMP_w_rmw_a16,opCMP_b_rm_a16, opCMP_w_rm_a16, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a16, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a16, opARPL_a16, opFS_w_a16, opGS_w_a16, op_66, op_67, opPUSH_imm_w, opIMUL_w_iw_a16,opPUSH_imm_bw, opIMUL_w_ib_a16,opINSB_a16, opINSW_a16, opOUTSB_a16, opOUTSW_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_w_a16, op80_a16, op83_w_a16, opTEST_b_a16, opTEST_w_a16, opXCHG_b_a16, opXCHG_w_a16, opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, opMOV_w_seg_a16,opLEA_w_a16, opMOV_seg_w_a16,opPOPW_a16, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_AX_a16, opMOV_a16_AL, opMOV_a16_AX, opMOVSB_a16, opMOVSW_a16, opCMPSB_a16, opCMPSW_a16, opTEST_AL, opTEST_AX, opSTOSB_a16, opSTOSW_a16, opLODSB_a16, opLODSW_a16, opSCASB_a16, opSCASW_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET, -/*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a16,opADD_l_rmw_a16,opADD_b_rm_a16, opADD_l_rm_a16, opADD_AL_imm, opADD_EAX_imm, opPUSH_ES_l, opPOP_ES_l, opOR_b_rmw_a16, opOR_l_rmw_a16, opOR_b_rm_a16, opOR_l_rm_a16, opOR_AL_imm, opOR_EAX_imm, opPUSH_CS_l, op0F_l_a16, -/*10*/ opADC_b_rmw_a16,opADC_l_rmw_a16,opADC_b_rm_a16, opADC_l_rm_a16, opADC_AL_imm, opADC_EAX_imm, opPUSH_SS_l, opPOP_SS_l, opSBB_b_rmw_a16,opSBB_l_rmw_a16,opSBB_b_rm_a16, opSBB_l_rm_a16, opSBB_AL_imm, opSBB_EAX_imm, opPUSH_DS_l, opPOP_DS_l, -/*20*/ opAND_b_rmw_a16,opAND_l_rmw_a16,opAND_b_rm_a16, opAND_l_rm_a16, opAND_AL_imm, opAND_EAX_imm, opES_l_a16, opDAA, opSUB_b_rmw_a16,opSUB_l_rmw_a16,opSUB_b_rm_a16, opSUB_l_rm_a16, opSUB_AL_imm, opSUB_EAX_imm, opCS_l_a16, opDAS, -/*30*/ opXOR_b_rmw_a16,opXOR_l_rmw_a16,opXOR_b_rm_a16, opXOR_l_rm_a16, opXOR_AL_imm, opXOR_EAX_imm, opSS_l_a16, opAAA, opCMP_b_rmw_a16,opCMP_l_rmw_a16,opCMP_b_rm_a16, opCMP_l_rm_a16, opCMP_AL_imm, opCMP_EAX_imm, opDS_l_a16, opAAS, - -/*40*/ opINC_EAX, opINC_ECX, opINC_EDX, opINC_EBX, opINC_ESP, opINC_EBP, opINC_ESI, opINC_EDI, opDEC_EAX, opDEC_ECX, opDEC_EDX, opDEC_EBX, opDEC_ESP, opDEC_EBP, opDEC_ESI, opDEC_EDI, -/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, -/*60*/ opPUSHA_l, opPOPA_l, opBOUND_l_a16, opARPL_a16, opFS_l_a16, opGS_l_a16, op_66, op_67, opPUSH_imm_l, opIMUL_l_il_a16,opPUSH_imm_bl, opIMUL_l_ib_a16,opINSB_a16, opINSL_a16, opOUTSB_a16, opOUTSL_a16, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a16, op81_l_a16, op80_a16, op83_l_a16, opTEST_b_a16, opTEST_l_a16, opXCHG_b_a16, opXCHG_l_a16, opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, opMOV_l_seg_a16,opLEA_l_a16, opMOV_seg_w_a16,opPOPL_a16, -/*90*/ opNOP, opXCHG_EAX_ECX, opXCHG_EAX_EDX, opXCHG_EAX_EBX, opXCHG_EAX_ESP, opXCHG_EAX_EBP, opXCHG_EAX_ESI, opXCHG_EAX_EDI, opCWDE, opCDQ, opCALL_far_l, opWAIT, opPUSHFD, opPOPFD, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a16, opMOV_EAX_a16, opMOV_a16_AL, opMOV_a16_EAX, opMOVSB_a16, opMOVSL_a16, opCMPSB_a16, opCMPSL_a16, opTEST_AL, opTEST_EAX, opSTOSB_a16, opSTOSL_a16, opLODSB_a16, opLODSL_a16, opSCASB_a16, opSCASL_a16, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_EAX_imm, opMOV_ECX_imm, opMOV_EDX_imm, opMOV_EBX_imm, opMOV_ESP_imm, opMOV_EBP_imm, opMOV_ESI_imm, opMOV_EDI_imm, - -/*c0*/ opC0_a16, opC1_l_a16, opRET_l_imm, opRET_l, opLES_l_a16, opLDS_l_a16, opMOV_b_imm_a16,opMOV_l_imm_a16,opENTER_l, opLEAVE_l, opRETF_a32_imm, opRETF_a32, opINT3, opINT, opINTO, opIRETD, -/*d0*/ opD0_a16, opD1_l_a16, opD2_a16, opD3_l_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, -/*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, -/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_l_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_l_a16, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a32,opADD_w_rmw_a32,opADD_b_rm_a32, opADD_w_rm_a32, opADD_AL_imm, opADD_AX_imm, opPUSH_ES_w, opPOP_ES_w, opOR_b_rmw_a32, opOR_w_rmw_a32, opOR_b_rm_a32, opOR_w_rm_a32, opOR_AL_imm, opOR_AX_imm, opPUSH_CS_w, op0F_w_a32, -/*10*/ opADC_b_rmw_a32,opADC_w_rmw_a32,opADC_b_rm_a32, opADC_w_rm_a32, opADC_AL_imm, opADC_AX_imm, opPUSH_SS_w, opPOP_SS_w, opSBB_b_rmw_a32,opSBB_w_rmw_a32,opSBB_b_rm_a32, opSBB_w_rm_a32, opSBB_AL_imm, opSBB_AX_imm, opPUSH_DS_w, opPOP_DS_w, -/*20*/ opAND_b_rmw_a32,opAND_w_rmw_a32,opAND_b_rm_a32, opAND_w_rm_a32, opAND_AL_imm, opAND_AX_imm, opES_w_a32, opDAA, opSUB_b_rmw_a32,opSUB_w_rmw_a32,opSUB_b_rm_a32, opSUB_w_rm_a32, opSUB_AL_imm, opSUB_AX_imm, opCS_w_a32, opDAS, -/*30*/ opXOR_b_rmw_a32,opXOR_w_rmw_a32,opXOR_b_rm_a32, opXOR_w_rm_a32, opXOR_AL_imm, opXOR_AX_imm, opSS_w_a32, opAAA, opCMP_b_rmw_a32,opCMP_w_rmw_a32,opCMP_b_rm_a32, opCMP_w_rm_a32, opCMP_AL_imm, opCMP_AX_imm, opDS_w_a32, opAAS, - -/*40*/ opINC_AX, opINC_CX, opINC_DX, opINC_BX, opINC_SP, opINC_BP, opINC_SI, opINC_DI, opDEC_AX, opDEC_CX, opDEC_DX, opDEC_BX, opDEC_SP, opDEC_BP, opDEC_SI, opDEC_DI, -/*50*/ opPUSH_AX, opPUSH_CX, opPUSH_DX, opPUSH_BX, opPUSH_SP, opPUSH_BP, opPUSH_SI, opPUSH_DI, opPOP_AX, opPOP_CX, opPOP_DX, opPOP_BX, opPOP_SP, opPOP_BP, opPOP_SI, opPOP_DI, -/*60*/ opPUSHA_w, opPOPA_w, opBOUND_w_a32, opARPL_a32, opFS_w_a32, opGS_w_a32, op_66, op_67, opPUSH_imm_w, opIMUL_w_iw_a32,opPUSH_imm_bw, opIMUL_w_ib_a32,opINSB_a32, opINSW_a32, opOUTSB_a32, opOUTSW_a32, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a32, op81_w_a32, op80_a32, op83_w_a32, opTEST_b_a32, opTEST_w_a32, opXCHG_b_a32, opXCHG_w_a32, opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, opMOV_w_seg_a32,opLEA_w_a32, opMOV_seg_w_a32,opPOPW_a32, -/*90*/ opNOP, opXCHG_AX_CX, opXCHG_AX_DX, opXCHG_AX_BX, opXCHG_AX_SP, opXCHG_AX_BP, opXCHG_AX_SI, opXCHG_AX_DI, opCBW, opCWD, opCALL_far_w, opWAIT, opPUSHF, opPOPF, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a32, opMOV_AX_a32, opMOV_a32_AL, opMOV_a32_AX, opMOVSB_a32, opMOVSW_a32, opCMPSB_a32, opCMPSW_a32, opTEST_AL, opTEST_AX, opSTOSB_a32, opSTOSW_a32, opLODSB_a32, opLODSW_a32, opSCASB_a32, opSCASW_a32, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_AX_imm, opMOV_CX_imm, opMOV_DX_imm, opMOV_BX_imm, opMOV_SP_imm, opMOV_BP_imm, opMOV_SI_imm, opMOV_DI_imm, - -/*c0*/ opC0_a32, opC1_w_a32, opRET_w_imm, opRET_w, opLES_w_a32, opLDS_w_a32, opMOV_b_imm_a32,opMOV_w_imm_a32,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET, -/*d0*/ opD0_a32, opD1_w_a32, opD2_a32, opD3_w_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, -/*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_w_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_w_a32, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ opADD_b_rmw_a32,opADD_l_rmw_a32,opADD_b_rm_a32, opADD_l_rm_a32, opADD_AL_imm, opADD_EAX_imm, opPUSH_ES_l, opPOP_ES_l, opOR_b_rmw_a32, opOR_l_rmw_a32, opOR_b_rm_a32, opOR_l_rm_a32, opOR_AL_imm, opOR_EAX_imm, opPUSH_CS_l, op0F_l_a32, -/*10*/ opADC_b_rmw_a32,opADC_l_rmw_a32,opADC_b_rm_a32, opADC_l_rm_a32, opADC_AL_imm, opADC_EAX_imm, opPUSH_SS_l, opPOP_SS_l, opSBB_b_rmw_a32,opSBB_l_rmw_a32,opSBB_b_rm_a32, opSBB_l_rm_a32, opSBB_AL_imm, opSBB_EAX_imm, opPUSH_DS_l, opPOP_DS_l, -/*20*/ opAND_b_rmw_a32,opAND_l_rmw_a32,opAND_b_rm_a32, opAND_l_rm_a32, opAND_AL_imm, opAND_EAX_imm, opES_l_a32, opDAA, opSUB_b_rmw_a32,opSUB_l_rmw_a32,opSUB_b_rm_a32, opSUB_l_rm_a32, opSUB_AL_imm, opSUB_EAX_imm, opCS_l_a32, opDAS, -/*30*/ opXOR_b_rmw_a32,opXOR_l_rmw_a32,opXOR_b_rm_a32, opXOR_l_rm_a32, opXOR_AL_imm, opXOR_EAX_imm, opSS_l_a32, opAAA, opCMP_b_rmw_a32,opCMP_l_rmw_a32,opCMP_b_rm_a32, opCMP_l_rm_a32, opCMP_AL_imm, opCMP_EAX_imm, opDS_l_a32, opAAS, - -/*40*/ opINC_EAX, opINC_ECX, opINC_EDX, opINC_EBX, opINC_ESP, opINC_EBP, opINC_ESI, opINC_EDI, opDEC_EAX, opDEC_ECX, opDEC_EDX, opDEC_EBX, opDEC_ESP, opDEC_EBP, opDEC_ESI, opDEC_EDI, -/*50*/ opPUSH_EAX, opPUSH_ECX, opPUSH_EDX, opPUSH_EBX, opPUSH_ESP, opPUSH_EBP, opPUSH_ESI, opPUSH_EDI, opPOP_EAX, opPOP_ECX, opPOP_EDX, opPOP_EBX, opPOP_ESP, opPOP_EBP, opPOP_ESI, opPOP_EDI, -/*60*/ opPUSHA_l, opPOPA_l, opBOUND_l_a32, opARPL_a32, opFS_l_a32, opGS_l_a32, op_66, op_67, opPUSH_imm_l, opIMUL_l_il_a32,opPUSH_imm_bl, opIMUL_l_ib_a32,opINSB_a32, opINSL_a32, opOUTSB_a32, opOUTSL_a32, -/*70*/ opJO, opJNO, opJB, opJNB, opJE, opJNE, opJBE, opJNBE, opJS, opJNS, opJP, opJNP, opJL, opJNL, opJLE, opJNLE, - -/*80*/ op80_a32, op81_l_a32, op80_a32, op83_l_a32, opTEST_b_a32, opTEST_l_a32, opXCHG_b_a32, opXCHG_l_a32, opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, opMOV_l_seg_a32,opLEA_l_a32, opMOV_seg_w_a32,opPOPL_a32, -/*90*/ opNOP, opXCHG_EAX_ECX, opXCHG_EAX_EDX, opXCHG_EAX_EBX, opXCHG_EAX_ESP, opXCHG_EAX_EBP, opXCHG_EAX_ESI, opXCHG_EAX_EDI, opCWDE, opCDQ, opCALL_far_l, opWAIT, opPUSHFD, opPOPFD, opSAHF, opLAHF, -/*a0*/ opMOV_AL_a32, opMOV_EAX_a32, opMOV_a32_AL, opMOV_a32_EAX, opMOVSB_a32, opMOVSL_a32, opCMPSB_a32, opCMPSL_a32, opTEST_AL, opTEST_EAX, opSTOSB_a32, opSTOSL_a32, opLODSB_a32, opLODSL_a32, opSCASB_a32, opSCASL_a32, -/*b0*/ opMOV_AL_imm, opMOV_CL_imm, opMOV_DL_imm, opMOV_BL_imm, opMOV_AH_imm, opMOV_CH_imm, opMOV_DH_imm, opMOV_BH_imm, opMOV_EAX_imm, opMOV_ECX_imm, opMOV_EDX_imm, opMOV_EBX_imm, opMOV_ESP_imm, opMOV_EBP_imm, opMOV_ESI_imm, opMOV_EDI_imm, - -/*c0*/ opC0_a32, opC1_l_a32, opRET_l_imm, opRET_l, opLES_l_a32, opLDS_l_a32, opMOV_b_imm_a32,opMOV_l_imm_a32,opENTER_l, opLEAVE_l, opRETF_a32_imm, opRETF_a32, opINT3, opINT, opINTO, opIRETD, -/*d0*/ opD0_a32, opD1_l_a32, opD2_a32, opD3_l_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, -/*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, -/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, -}; - -const OpFn OP_TABLE(REPE)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a16,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_w_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPE_w_a16,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPE_w_a16,opGS_REPE_w_a16,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_E,opREP_CMPSW_a16_E,0, 0, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_E,opREP_SCASW_a16_E, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a16,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_l_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPE_l_a16,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPE_l_a16,opGS_REPE_l_a16,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_E,opREP_CMPSL_a16_E,0, 0, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_E,opREP_SCASL_a16_E, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_w_a32,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_w_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPE_w_a32,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPE_w_a32,opGS_REPE_w_a32,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_E,opREP_CMPSW_a32_E,0, 0, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_E,opREP_SCASW_a32_E, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPE_l_a32,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPE_l_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPE_l_a32,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPE_l_a32,opGS_REPE_l_a32,op_66_REPE, op_67_REPE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_E,opREP_CMPSL_a32_E,0, 0, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_E,opREP_SCASL_a32_E, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; - -const OpFn OP_TABLE(REPNE)[1024] = -{ - /*16-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a16,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_w_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_w_a16,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPNE_w_a16,opGS_REPNE_w_a16,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSW_a16, opREP_OUTSB_a16,opREP_OUTSW_a16, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSW_a16,opREP_CMPSB_a16_NE,opREP_CMPSW_a16_NE,0, 0, opREP_STOSB_a16,opREP_STOSW_a16,opREP_LODSB_a16,opREP_LODSW_a16,opREP_SCASB_a16_NE,opREP_SCASW_a16_NE, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*32-bit data, 16-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a16,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a16,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_l_a16,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_l_a16,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPNE_l_a16,opGS_REPNE_l_a16,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a16, opREP_INSL_a16, opREP_OUTSB_a16,opREP_OUTSL_a16, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a16,opREP_MOVSL_a16,opREP_CMPSB_a16_NE,opREP_CMPSL_a16_NE,0, 0, opREP_STOSB_a16,opREP_STOSL_a16,opREP_LODSB_a16,opREP_LODSL_a16,opREP_SCASB_a16_NE,opREP_SCASL_a16_NE, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*16-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_w_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_w_a32,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_w_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_w_a32,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPNE_w_a32,opGS_REPNE_w_a32,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSW_a32, opREP_OUTSB_a32,opREP_OUTSW_a32, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSW_a32,opREP_CMPSB_a32_NE,opREP_CMPSW_a32_NE,0, 0, opREP_STOSB_a32,opREP_STOSW_a32,opREP_LODSB_a32,opREP_LODSW_a32,opREP_SCASB_a32_NE,opREP_SCASW_a32_NE, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - - /*32-bit data, 32-bit addr*/ -/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ -/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*20*/ 0, 0, 0, 0, 0, 0, opES_REPNE_l_a32,0, 0, 0, 0, 0, 0, 0, opCS_REPNE_l_a32,0, -/*30*/ 0, 0, 0, 0, 0, 0, opSS_REPNE_l_a32,0, 0, 0, 0, 0, 0, 0, opDS_REPNE_l_a32,0, - -/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*60*/ 0, 0, 0, 0, opFS_REPNE_l_a32,opGS_REPNE_l_a32,op_66_REPNE, op_67_REPNE, 0, 0, 0, 0, opREP_INSB_a32, opREP_INSL_a32, opREP_OUTSB_a32,opREP_OUTSL_a32, -/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*a0*/ 0, 0, 0, 0, opREP_MOVSB_a32,opREP_MOVSL_a32,opREP_CMPSB_a32_NE,opREP_CMPSL_a32_NE,0, 0, opREP_STOSB_a32,opREP_STOSL_a32,opREP_LODSB_a32,opREP_LODSL_a32,opREP_SCASB_a32_NE,opREP_SCASL_a32_NE, -/*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -/*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -/*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -}; diff --git a/src/cpu/codegen.c b/src/cpu/codegen.c index d951f650c..44b1c502d 100644 --- a/src/cpu/codegen.c +++ b/src/cpu/codegen.c @@ -2,8 +2,9 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" + +#include "86box.h" +#include "mem.h" #include "cpu.h" #include "x86_ops.h" #include "codegen.h" diff --git a/src/cpu/codegen.h b/src/cpu/codegen.h index 38847f78b..f7c41f849 100644 --- a/src/cpu/codegen.h +++ b/src/cpu/codegen.h @@ -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)(); diff --git a/src/cpu/codegen_ops.c b/src/cpu/codegen_ops.c index a577d3b6e..229fa1882 100644 --- a/src/cpu/codegen_ops.c +++ b/src/cpu/codegen_ops.c @@ -2,8 +2,9 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" + +#include "86box.h" +#include "mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu/codegen_ops_x86-64.h b/src/cpu/codegen_ops_x86-64.h index de6763561..9508a83bd 100644 --- a/src/cpu/codegen_ops_x86-64.h +++ b/src/cpu/codegen_ops_x86-64.h @@ -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]*/ diff --git a/src/cpu/codegen_ops_x86.h b/src/cpu/codegen_ops_x86.h index 225490cd3..13ca37c4c 100644 --- a/src/cpu/codegen_ops_x86.h +++ b/src/cpu/codegen_ops_x86.h @@ -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() { diff --git a/src/cpu/codegen_timing_486.c b/src/cpu/codegen_timing_486.c index 3f45d117e..912bfc16b 100644 --- a/src/cpu/codegen_timing_486.c +++ b/src/cpu/codegen_timing_486.c @@ -2,8 +2,8 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" +#include "86box.h" +#include "mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu/codegen_timing_686.c b/src/cpu/codegen_timing_686.c index fc818d7f1..dc901dddc 100644 --- a/src/cpu/codegen_timing_686.c +++ b/src/cpu/codegen_timing_686.c @@ -12,8 +12,8 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" +#include "86box.h" +#include "mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu/codegen_timing_common.c b/src/cpu/codegen_timing_common.c index f53a8fc4d..c9ac19766 100644 --- a/src/cpu/codegen_timing_common.c +++ b/src/cpu/codegen_timing_common.c @@ -2,7 +2,7 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" #include "codegen_timing_common.h" diff --git a/src/cpu/codegen_timing_pentium.c b/src/cpu/codegen_timing_pentium.c index 88c4e9544..3a625ed6d 100644 --- a/src/cpu/codegen_timing_pentium.c +++ b/src/cpu/codegen_timing_pentium.c @@ -13,8 +13,8 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" +#include "86box.h" +#include "mem.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu/codegen_timing_winchip.c b/src/cpu/codegen_timing_winchip.c index 93717c4a6..7074307ef 100644 --- a/src/cpu/codegen_timing_winchip.c +++ b/src/cpu/codegen_timing_winchip.c @@ -2,7 +2,7 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu/codegen_x86-64.c b/src/cpu/codegen_x86-64.c index 42136207c..c0ece0ce0 100644 --- a/src/cpu/codegen_x86-64.c +++ b/src/cpu/codegen_x86-64.c @@ -5,13 +5,13 @@ #include #include #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" diff --git a/src/cpu/codegen_x86.c b/src/cpu/codegen_x86.c index a3352943f..b6fd2a49b 100644 --- a/src/cpu/codegen_x86.c +++ b/src/cpu/codegen_x86.c @@ -43,12 +43,12 @@ #include #include #include -#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" diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c deleted file mode 100644 index 891790823..000000000 --- a/src/cpu/cpu.c +++ /dev/null @@ -1,2363 +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. - * - * CPU type handler. - * - * Version: @(#)cpu.c 1.0.6 2018/05/05 - * - * Authors: Fred N. van Kempen, - * Sarah Walker, - * leilei, - * Miran Grca, - * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * 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. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "cpu.h" -#include "../device.h" -#include "../machine/machine.h" -#include "../io.h" -#include "x86_ops.h" -#include "../mem.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pci.h" -#ifdef USE_DYNAREC -# include "codegen.h" -#endif - - -#if 1 -static void cpu_write(uint16_t addr, uint8_t val, void *priv); -static uint8_t cpu_read(uint16_t addr, void *priv); -#endif - - -enum { - CPUID_FPU = (1 << 0), - CPUID_VME = (1 << 1), - CPUID_PSE = (1 << 3), - CPUID_TSC = (1 << 4), - CPUID_MSR = (1 << 5), - CPUID_CMPXCHG8B = (1 << 8), - CPUID_AMDSEP = (1 << 10), - CPUID_SEP = (1 << 11), - CPUID_CMOV = (1 << 15), - CPUID_MMX = (1 << 23), - CPUID_FXSR = (1 << 24) -}; - - -#ifdef USE_DYNAREC -const OpFn *x86_dynarec_opcodes; -const OpFn *x86_dynarec_opcodes_0f; -const OpFn *x86_dynarec_opcodes_d8_a16; -const OpFn *x86_dynarec_opcodes_d8_a32; -const OpFn *x86_dynarec_opcodes_d9_a16; -const OpFn *x86_dynarec_opcodes_d9_a32; -const OpFn *x86_dynarec_opcodes_da_a16; -const OpFn *x86_dynarec_opcodes_da_a32; -const OpFn *x86_dynarec_opcodes_db_a16; -const OpFn *x86_dynarec_opcodes_db_a32; -const OpFn *x86_dynarec_opcodes_dc_a16; -const OpFn *x86_dynarec_opcodes_dc_a32; -const OpFn *x86_dynarec_opcodes_dd_a16; -const OpFn *x86_dynarec_opcodes_dd_a32; -const OpFn *x86_dynarec_opcodes_de_a16; -const OpFn *x86_dynarec_opcodes_de_a32; -const OpFn *x86_dynarec_opcodes_df_a16; -const OpFn *x86_dynarec_opcodes_df_a32; -const OpFn *x86_dynarec_opcodes_REPE; -const OpFn *x86_dynarec_opcodes_REPNE; -#endif - -const OpFn *x86_opcodes; -const OpFn *x86_opcodes_0f; -const OpFn *x86_opcodes_d8_a16; -const OpFn *x86_opcodes_d8_a32; -const OpFn *x86_opcodes_d9_a16; -const OpFn *x86_opcodes_d9_a32; -const OpFn *x86_opcodes_da_a16; -const OpFn *x86_opcodes_da_a32; -const OpFn *x86_opcodes_db_a16; -const OpFn *x86_opcodes_db_a32; -const OpFn *x86_opcodes_dc_a16; -const OpFn *x86_opcodes_dc_a32; -const OpFn *x86_opcodes_dd_a16; -const OpFn *x86_opcodes_dd_a32; -const OpFn *x86_opcodes_de_a16; -const OpFn *x86_opcodes_de_a32; -const OpFn *x86_opcodes_df_a16; -const OpFn *x86_opcodes_df_a32; -const OpFn *x86_opcodes_REPE; -const OpFn *x86_opcodes_REPNE; - -int in_smm = 0, smi_line = 0, smi_latched = 0; -uint32_t smbase = 0x30000; - -CPU *cpu_s; -int cpu_effective; -int cpu_multi; -int cpu_16bitbus; -int cpu_busspeed; -int cpu_cyrix_alignment; -int CPUID; -uint64_t cpu_CR4_mask; -int isa_cycles; -int cpu_cycles_read, cpu_cycles_read_l, - cpu_cycles_write, cpu_cycles_write_l; -int cpu_prefetch_cycles, cpu_prefetch_width, - cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles; -int cpu_waitstates; -int cpu_cache_int_enabled, cpu_cache_ext_enabled; -int cpu_pci_speed, cpu_alt_reset; - -uint32_t cpu_features; - -int is286, - is386, - is486, - cpu_iscyrix, - isibmcpu, - israpidcad, - is_pentium; - -int hasfpu; - - -uint64_t tsc = 0; -msr_t msr; -cr0_t CR0; -uint64_t pmc[2] = {0, 0}; - -uint16_t temp_seg_data[4] = {0, 0, 0, 0}; - -#if defined(DEV_BRANCH) && defined(USE_I686) -uint16_t cs_msr = 0; -uint32_t esp_msr = 0; -uint32_t eip_msr = 0; -uint64_t apic_base_msr = 0; -uint64_t mtrr_cap_msr = 0; -uint64_t mtrr_physbase_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t mtrr_physmask_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t mtrr_fix64k_8000_msr = 0; -uint64_t mtrr_fix16k_8000_msr = 0; -uint64_t mtrr_fix16k_a000_msr = 0; -uint64_t mtrr_fix4k_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t pat_msr = 0; -uint64_t mtrr_deftype_msr = 0; -uint64_t msr_ia32_pmc[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t ecx17_msr = 0; -uint64_t ecx79_msr = 0; -uint64_t ecx8x_msr[4] = {0, 0, 0, 0}; -uint64_t ecx116_msr = 0; -uint64_t ecx11x_msr[4] = {0, 0, 0, 0}; -uint64_t ecx11e_msr = 0; -uint64_t ecx186_msr = 0; -uint64_t ecx187_msr = 0; -uint64_t ecx1e0_msr = 0; -uint64_t ecx570_msr = 0; -#endif - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) -uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ -uint64_t star = 0; /* These are K6-only. */ -uint64_t sfmask = 0; -#endif - -int timing_rr; -int timing_mr, timing_mrl; -int timing_rm, timing_rml; -int timing_mm, timing_mml; -int timing_bt, timing_bnt; -int timing_int, timing_int_rm, timing_int_v86, timing_int_pm, - timing_int_pm_outer; -int timing_iret_rm, timing_iret_v86, timing_iret_pm, - timing_iret_pm_outer; -int timing_call_rm, timing_call_pm, timing_call_pm_gate, - timing_call_pm_gate_inner; -int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; -int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; -int timing_misaligned; - - -static uint8_t ccr0, ccr1, ccr2, ccr3, ccr4, ccr5, ccr6; - -int cpu_has_feature(int feature) -{ - return cpu_features & feature; -} - - -void -cpu_dynamic_switch(int new_cpu) -{ - if (cpu_effective == new_cpu) - return; - - int c = cpu; - cpu = new_cpu; - cpu_set(); - pc_speed_changed(); - cpu = c; -} - - -void -cpu_set_edx(void) -{ - EDX = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].edx_reset; -} - - -void -cpu_set(void) -{ - if (!machines[machine].cpu[cpu_manufacturer].cpus) - { - /*CPU is invalid, set to default*/ - cpu_manufacturer = 0; - cpu = 0; - } - - cpu_effective = cpu; - cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; - - cpu_alt_reset = 0; - - CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088); - is286 = (cpu_s->cpu_type >= CPU_286); - is386 = (cpu_s->cpu_type >= CPU_386SX); - isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); - israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); - is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); - hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); -#else - cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86); -#endif - - cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); - - if (cpu_s->multi) { - cpu_busspeed = cpu_s->rspeed / cpu_s->multi; - } - cpu_multi = cpu_s->multi; - ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; - - if ((cpu_s->cpu_type == CPU_8088) || (cpu_s->cpu_type == CPU_8086) || - (cpu_s->cpu_type == CPU_286) || (cpu_s->cpu_type == CPU_386SX) || - (cpu_s->cpu_type == CPU_386DX) || (cpu_s->cpu_type == CPU_i486SX)) { - hasfpu = !!enable_external_fpu; - } - - cpu_update_waitstates(); - - isa_cycles = cpu_s->atclk_div; - - if (cpu_s->rspeed <= 8000000) - cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; - else - cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; - - if (cpu_s->pci_speed) - { - pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed; - pci_burst_time = cpu_s->rspeed / cpu_s->pci_speed; - } - else - { - pci_nonburst_time = 4; - pci_burst_time = 1; - } - - if (cpu_iscyrix) - io_sethandler(0x0022, 0x0002, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); - else - io_removehandler(0x0022, 0x0002, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); - - if (hasfpu) - io_sethandler(0x00f0, 0x000f, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); - else - io_removehandler(0x00f0, 0x000f, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); - -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); -#else - x86_setopcodes(ops_386, ops_386_0f); -#endif - x86_opcodes_REPE = ops_REPE; - x86_opcodes_REPNE = ops_REPNE; -#ifdef USE_DYNAREC - x86_dynarec_opcodes_REPE = dynarec_ops_REPE; - x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; -#endif - -#ifdef USE_DYNAREC - if (hasfpu) - { - x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; - x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; - } - else - { - x86_dynarec_opcodes_d8_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_d8_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_d9_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_nofpu_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_nofpu_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32; - } - codegen_timing_set(&codegen_timing_486); -#endif - - if (hasfpu) - { - x86_opcodes_d8_a16 = ops_fpu_d8_a16; - x86_opcodes_d8_a32 = ops_fpu_d8_a32; - x86_opcodes_d9_a16 = ops_fpu_d9_a16; - x86_opcodes_d9_a32 = ops_fpu_d9_a32; - x86_opcodes_da_a16 = ops_fpu_da_a16; - x86_opcodes_da_a32 = ops_fpu_da_a32; - x86_opcodes_db_a16 = ops_fpu_db_a16; - x86_opcodes_db_a32 = ops_fpu_db_a32; - x86_opcodes_dc_a16 = ops_fpu_dc_a16; - x86_opcodes_dc_a32 = ops_fpu_dc_a32; - x86_opcodes_dd_a16 = ops_fpu_dd_a16; - x86_opcodes_dd_a32 = ops_fpu_dd_a32; - x86_opcodes_de_a16 = ops_fpu_de_a16; - x86_opcodes_de_a32 = ops_fpu_de_a32; - x86_opcodes_df_a16 = ops_fpu_df_a16; - x86_opcodes_df_a32 = ops_fpu_df_a32; - } - else - { - x86_opcodes_d8_a16 = ops_nofpu_a16; - x86_opcodes_d8_a32 = ops_nofpu_a32; - x86_opcodes_d9_a16 = ops_nofpu_a16; - x86_opcodes_d9_a32 = ops_nofpu_a32; - x86_opcodes_da_a16 = ops_nofpu_a16; - x86_opcodes_da_a32 = ops_nofpu_a32; - x86_opcodes_db_a16 = ops_nofpu_a16; - x86_opcodes_db_a32 = ops_nofpu_a32; - x86_opcodes_dc_a16 = ops_nofpu_a16; - x86_opcodes_dc_a32 = ops_nofpu_a32; - x86_opcodes_dd_a16 = ops_nofpu_a16; - x86_opcodes_dd_a32 = ops_nofpu_a32; - x86_opcodes_de_a16 = ops_nofpu_a16; - x86_opcodes_de_a32 = ops_nofpu_a32; - x86_opcodes_df_a16 = ops_nofpu_a16; - x86_opcodes_df_a32 = ops_nofpu_a32; - } - - memset(&msr, 0, sizeof(msr)); - - timing_misaligned = 0; - cpu_cyrix_alignment = 0; - - switch (cpu_s->cpu_type) - { - case CPU_8088: - case CPU_8086: - break; - - case CPU_286: -#ifdef USE_DYNAREC - x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f); -#else - x86_setopcodes(ops_286, ops_286_0f); -#endif - if (enable_external_fpu) - { -#ifdef USE_DYNAREC - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; -#endif - x86_opcodes_d9_a16 = ops_fpu_287_d9_a16; - x86_opcodes_d9_a32 = ops_fpu_287_d9_a32; - x86_opcodes_da_a16 = ops_fpu_287_da_a16; - x86_opcodes_da_a32 = ops_fpu_287_da_a32; - x86_opcodes_db_a16 = ops_fpu_287_db_a16; - x86_opcodes_db_a32 = ops_fpu_287_db_a32; - x86_opcodes_dc_a16 = ops_fpu_287_dc_a16; - x86_opcodes_dc_a32 = ops_fpu_287_dc_a32; - x86_opcodes_dd_a16 = ops_fpu_287_dd_a16; - x86_opcodes_dd_a32 = ops_fpu_287_dd_a32; - x86_opcodes_de_a16 = ops_fpu_287_de_a16; - x86_opcodes_de_a32 = ops_fpu_287_de_a32; - x86_opcodes_df_a16 = ops_fpu_287_df_a16; - x86_opcodes_df_a32 = ops_fpu_287_df_a32; - } - timing_rr = 2; /*register dest - register src*/ - timing_rm = 7; /*register dest - memory src*/ - timing_mr = 7; /*memory dest - register src*/ - timing_mm = 7; /*memory dest - memory src*/ - timing_rml = 9; /*register dest - memory src long*/ - timing_mrl = 11; /*memory dest - register src long*/ - timing_mml = 11; /*memory dest - memory src*/ - timing_bt = 7-3; /*branch taken*/ - timing_bnt = 3; /*branch not taken*/ - timing_int = 0; - timing_int_rm = 23; - timing_int_v86 = 0; - timing_int_pm = 40; - timing_int_pm_outer = 78; - timing_iret_rm = 17; - timing_iret_v86 = 0; - timing_iret_pm = 31; - timing_iret_pm_outer = 55; - timing_call_rm = 13; - timing_call_pm = 26; - timing_call_pm_gate = 52; - timing_call_pm_gate_inner = 82; - timing_retf_rm = 15; - timing_retf_pm = 25; - timing_retf_pm_outer = 55; - timing_jmp_rm = 11; - timing_jmp_pm = 23; - timing_jmp_pm_gate = 38; - break; - - case CPU_IBM386SLC: - case CPU_386SX: - timing_rr = 2; /*register dest - register src*/ - timing_rm = 6; /*register dest - memory src*/ - timing_mr = 7; /*memory dest - register src*/ - timing_mm = 6; /*memory dest - memory src*/ - timing_rml = 8; /*register dest - memory src long*/ - timing_mrl = 11; /*memory dest - register src long*/ - timing_mml = 10; /*memory dest - memory src*/ - timing_bt = 7-3; /*branch taken*/ - timing_bnt = 3; /*branch not taken*/ - timing_int = 0; - timing_int_rm = 37; - timing_int_v86 = 59; - timing_int_pm = 99; - timing_int_pm_outer = 119; - timing_iret_rm = 22; - timing_iret_v86 = 60; - timing_iret_pm = 38; - timing_iret_pm_outer = 82; - timing_call_rm = 17; - timing_call_pm = 34; - timing_call_pm_gate = 52; - timing_call_pm_gate_inner = 86; - timing_retf_rm = 18; - timing_retf_pm = 32; - timing_retf_pm_outer = 68; - timing_jmp_rm = 12; - timing_jmp_pm = 27; - timing_jmp_pm_gate = 45; - break; - - case CPU_386DX: - timing_rr = 2; /*register dest - register src*/ - timing_rm = 6; /*register dest - memory src*/ - timing_mr = 7; /*memory dest - register src*/ - timing_mm = 6; /*memory dest - memory src*/ - timing_rml = 6; /*register dest - memory src long*/ - timing_mrl = 7; /*memory dest - register src long*/ - timing_mml = 6; /*memory dest - memory src*/ - timing_bt = 7-3; /*branch taken*/ - timing_bnt = 3; /*branch not taken*/ - timing_int = 0; - timing_int_rm = 37; - timing_int_v86 = 59; - timing_int_pm = 99; - timing_int_pm_outer = 119; - timing_iret_rm = 22; - timing_iret_v86 = 60; - timing_iret_pm = 38; - timing_iret_pm_outer = 82; - timing_call_rm = 17; - timing_call_pm = 34; - timing_call_pm_gate = 52; - timing_call_pm_gate_inner = 86; - timing_retf_rm = 18; - timing_retf_pm = 32; - timing_retf_pm_outer = 68; - timing_jmp_rm = 12; - timing_jmp_pm = 27; - timing_jmp_pm_gate = 45; - break; - - case CPU_IBM486SLC: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 5; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 4; /*register dest - memory src long*/ - timing_mrl = 5; /*memory dest - register src long*/ - timing_mml = 5; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /*unknown*/ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; - timing_misaligned = 3; - break; - - case CPU_IBM486BL: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /*unknown*/ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; - timing_misaligned = 3; - break; - - case CPU_RAPIDCAD: - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /*unknown*/ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; - break; - - case CPU_486SLC: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 3; /*register dest - memory src*/ - timing_mr = 5; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 5; /*register dest - memory src long*/ - timing_mrl = 7; /*memory dest - register src long*/ - timing_mml = 7; - timing_bt = 6-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - /*unknown*/ - timing_int = 4; - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; - timing_misaligned = 3; - break; - - case CPU_486DLC: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 3; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 3; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 6-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - /*unknown*/ - timing_int = 4; - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; - timing_misaligned = 3; - break; - - case CPU_iDX4: - cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; - case CPU_i486SX: - case CPU_i486DX: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /*unknown*/ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; - timing_misaligned = 3; - break; - - case CPU_Am486SX: - case CPU_Am486DX: - /*AMD timing identical to Intel*/ -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 15; - timing_iret_v86 = 36; /*unknown*/ - timing_iret_pm = 20; - timing_iret_pm_outer = 36; - timing_call_rm = 18; - timing_call_pm = 20; - timing_call_pm_gate = 35; - timing_call_pm_gate_inner = 69; - timing_retf_rm = 13; - timing_retf_pm = 17; - timing_retf_pm_outer = 35; - timing_jmp_rm = 17; - timing_jmp_pm = 19; - timing_jmp_pm_gate = 32; - timing_misaligned = 3; - break; - - case CPU_Cx486S: - case CPU_Cx486DX: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 3; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 3; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 4-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 4; - timing_int_rm = 14; - timing_int_v86 = 82; - timing_int_pm = 49; - timing_int_pm_outer = 77; - timing_iret_rm = 14; - timing_iret_v86 = 66; /*unknown*/ - timing_iret_pm = 31; - timing_iret_pm_outer = 66; - timing_call_rm = 12; - timing_call_pm = 30; - timing_call_pm_gate = 41; - timing_call_pm_gate_inner = 83; - timing_retf_rm = 13; - timing_retf_pm = 26; - timing_retf_pm_outer = 61; - timing_jmp_rm = 9; - timing_jmp_pm = 26; - timing_jmp_pm_gate = 37; - timing_misaligned = 3; - break; - - case CPU_Cx5x86: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); -#else - x86_setopcodes(ops_386, ops_486_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 2; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 2; - timing_bt = 5-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 0; - timing_int_rm = 9; - timing_int_v86 = 82; /*unknown*/ - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; /*unknown*/ - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 4; - timing_call_pm = 15; - timing_call_pm_gate = 26; - timing_call_pm_gate_inner = 35; - timing_retf_rm = 4; - timing_retf_pm = 7; - timing_retf_pm_outer = 23; - timing_jmp_rm = 5; - timing_jmp_pm = 7; - timing_jmp_pm_gate = 17; - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - break; - - case CPU_WINCHIP: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_winchip_0f, dynarec_ops_386, dynarec_ops_winchip_0f); -#else - x86_setopcodes(ops_386, ops_winchip_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 3-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; - /*unknown*/ - timing_int_rm = 26; - timing_int_v86 = 82; - timing_int_pm = 44; - timing_int_pm_outer = 71; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 4; - timing_call_pm = 15; - timing_call_pm_gate = 26; - timing_call_pm_gate_inner = 35; - timing_retf_rm = 4; - timing_retf_pm = 7; - timing_retf_pm_outer = 23; - timing_jmp_rm = 5; - timing_jmp_pm = 7; - timing_jmp_pm_gate = 17; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_winchip); -#endif - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - break; - - case CPU_PENTIUM: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); -#else - x86_setopcodes(ops_386, ops_pentium_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 0; /*branch taken*/ - timing_bnt = 2; /*branch not taken*/ - timing_int = 6; - timing_int_rm = 11; - timing_int_v86 = 54; - timing_int_pm = 25; - timing_int_pm_outer = 42; - timing_iret_rm = 7; - timing_iret_v86 = 27; /*unknown*/ - timing_iret_pm = 10; - timing_iret_pm_outer = 27; - timing_call_rm = 4; - timing_call_pm = 4; - timing_call_pm_gate = 22; - timing_call_pm_gate_inner = 44; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 3; - timing_jmp_pm = 3; - timing_jmp_pm_gate = 18; - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_pentium); -#endif - break; - - case CPU_PENTIUMMMX: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); -#else - x86_setopcodes(ops_386, ops_pentiummmx_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_int = 6; - timing_int_rm = 11; - timing_int_v86 = 54; - timing_int_pm = 25; - timing_int_pm_outer = 42; - timing_iret_rm = 7; - timing_iret_v86 = 27; /*unknown*/ - timing_iret_pm = 10; - timing_iret_pm_outer = 27; - timing_call_rm = 4; - timing_call_pm = 4; - timing_call_pm_gate = 22; - timing_call_pm_gate_inner = 44; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 3; - timing_jmp_pm = 3; - timing_jmp_pm_gate = 18; - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_pentium); -#endif - break; - -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); -#else - x86_setopcodes(ops_386, ops_pentium_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 2; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 2; - timing_bt = 0; /*branch taken*/ - timing_bnt = 2; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; - timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - cpu_features = CPU_FEATURE_RDTSC; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - CPUID = 0; /*Disabled on powerup by default*/ - break; - - case CPU_Cx6x86L: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); -#else - x86_setopcodes(ops_386, ops_pentium_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 2; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 2; - timing_bt = 0; /*branch taken*/ - timing_bnt = 2; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; - timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - cpu_features = CPU_FEATURE_RDTSC; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - ccr4 = 0x80; - break; - - - case CPU_CxGX1: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); -#else - x86_setopcodes(ops_386, ops_pentium_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 2; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 2; - timing_bt = 5-1; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - break; - - - case CPU_Cx6x86MX: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_c6x86mx_0f, dynarec_ops_386, dynarec_ops_c6x86mx_0f); - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; -#else - x86_setopcodes(ops_386, ops_c6x86mx_0f); -#endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 2; /*memory dest - register src*/ - timing_mm = 2; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 2; /*memory dest - register src long*/ - timing_mml = 2; - timing_bt = 0; /*branch taken*/ - timing_bnt = 2; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; - timing_iret_rm = 7; - timing_iret_v86 = 26; - timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; - timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; - timing_retf_rm = 4; - timing_retf_pm = 4; - timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; - cpu_cyrix_alignment = 1; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - ccr4 = 0x80; - break; -#endif - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) - case CPU_K5: - case CPU_5K86: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); -#else - x86_setopcodes(ops_386, ops_k6_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; - break; - - case CPU_K6: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); -#else - x86_setopcodes(ops_386, ops_k6_0f); -#endif - timing_rr = 1; /*register dest - register src*/ - timing_rm = 2; /*register dest - memory src*/ - timing_mr = 3; /*memory dest - register src*/ - timing_mm = 3; - timing_rml = 2; /*register dest - memory src long*/ - timing_mrl = 3; /*memory dest - register src long*/ - timing_mml = 3; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_pentium); -#endif - break; -#endif - -#if defined(DEV_BRANCH) && defined(USE_I686) - case CPU_PENTIUMPRO: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; -#else - x86_setopcodes(ops_386, ops_pentiumpro_0f); -#endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - break; - -#if 0 - case CPU_PENTIUM2: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; -#else - x86_setopcodes(ops_386, ops_pentium2_0f); -#endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - break; -#endif - - case CPU_PENTIUM2D: -#ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_pentium2d_0f, dynarec_ops_386, dynarec_ops_pentium2d_0f); - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; -#else - x86_setopcodes(ops_386, ops_pentium2d_0f); -#endif - x86_opcodes_da_a16 = ops_fpu_686_da_a16; - x86_opcodes_da_a32 = ops_fpu_686_da_a32; - x86_opcodes_db_a16 = ops_fpu_686_db_a16; - x86_opcodes_db_a32 = ops_fpu_686_db_a32; - x86_opcodes_df_a16 = ops_fpu_686_df_a16; - x86_opcodes_df_a32 = ops_fpu_686_df_a32; - timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; - timing_bt = 0; /*branch taken*/ - timing_bnt = 1; /*branch not taken*/ - timing_misaligned = 3; - cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE | CR4_OSFXSR; -#ifdef USE_DYNAREC - codegen_timing_set(&codegen_timing_686); -#endif - break; -#endif - - default: - fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); - } -} - - -char * -cpu_current_pc(char *bufp) -{ - static char buff[10]; - - if (bufp == NULL) - bufp = buff; - - sprintf(bufp, "%04X:%04X", CS, cpu_state.pc); - - return(bufp); -} - - -void -cpu_CPUID(void) -{ - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) - { - case CPU_i486DX: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU; /*FPU*/ - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_iDX4: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_Am486SX: - if (!EAX) - { - EAX = 1; - EBX = 0x68747541; - ECX = 0x444D4163; - EDX = 0x69746E65; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = EDX = 0; /*No FPU*/ - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_Am486DX: - if (!EAX) - { - EAX = 1; - EBX = 0x68747541; - ECX = 0x444D4163; - EDX = 0x69746E65; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU; /*FPU*/ - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_WINCHIP: - if (!EAX) - { - EAX = 1; - if (msr.fcr2 & (1 << 14)) - { - EBX = msr.fcr3 >> 32; - ECX = msr.fcr3 & 0xffffffff; - EDX = msr.fcr2 >> 32; - } - else - { - EBX = 0x746e6543; /*CentaurHauls*/ - ECX = 0x736c7561; - EDX = 0x48727561; - } - } - else if (EAX == 1) - { - EAX = 0x540; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; - if (cpu_has_feature(CPU_FEATURE_CX8)) - EDX |= CPUID_CMPXCHG8B; - if (msr.fcr & (1 << 9)) - EDX |= CPUID_MMX; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_PENTIUM: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else - EAX = EBX = ECX = EDX = 0; - break; - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) - case CPU_K5: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_5K86: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else if (EAX == 0x80000000) - { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } - else if (EAX == 0x80000001) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else if (EAX == 0x80000002) - { - EAX = 0x2D444D41; - EBX = 0x7428354B; - ECX = 0x5020296D; - EDX = 0x65636F72; - } - else if (EAX == 0x80000003) - { - EAX = 0x726F7373; - EBX = ECX = EDX = 0; - } - else if (EAX == 0x80000004) - { - EAX = EBX = ECX = EDX = 0; - } - else if (EAX == 0x80000005) - { - EAX = 0; - EBX = 0x04800000; - ECX = 0x08040120; - EDX = 0x10040120; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - case CPU_K6: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x68747541; - EDX = 0x69746E65; - ECX = 0x444D4163; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else if (EAX == 0x80000000) - { - EAX = 0x80000005; - EBX = ECX = EDX = 0; - } - else if (EAX == 0x80000001) - { - EAX = CPUID + 0x100; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_AMDSEP; - } - else if (EAX == 0x80000002) - { - EAX = 0x2D444D41; - EBX = 0x6D74364B; - ECX = 0x202F7720; - EDX = 0x746C756D; - } - else if (EAX == 0x80000003) - { - EAX = 0x64656D69; - EBX = 0x65206169; - ECX = 0x6E657478; - EDX = 0x6E6F6973; - } - else if (EAX == 0x80000004) - { - EAX = 0x73; - EBX = ECX = EDX = 0; - } - else if (EAX == 0x80000005) - { - EAX = 0; - EBX = 0x02800140; - ECX = 0x20020220; - EDX = 0x20020220; - } - else if (EAX == 0x8FFFFFFF) - { - EAX = 0x4778654E; - EBX = 0x72656E65; - ECX = 0x6F697461; - EDX = 0x444D416E; - } - else - EAX = EBX = ECX = EDX = 0; - break; -#endif - - case CPU_PENTIUMMMX: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - - case CPU_Cx6x86L: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_CMPXCHG8B; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - - case CPU_CxGX1: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B; - } - else - EAX = EBX = ECX = EDX = 0; - break; - - - - case CPU_Cx6x86MX: - if (!EAX) - { - EAX = 0x00000001; - EBX = 0x69727943; - EDX = 0x736e4978; - ECX = 0x64616574; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX; - } - else - EAX = EBX = ECX = EDX = 0; - break; -#endif - -#ifdef DEV_BRANCH -#ifdef USE_I686 - case CPU_PENTIUMPRO: - if (!EAX) - { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_SEP | CPUID_CMOV; - } - else if (EAX == 2) - { - } - else - EAX = EBX = ECX = EDX = 0; - break; - - /* case CPU_PENTIUM2: - if (!EAX) - { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_CMOV; - } - else if (EAX == 2) - { - EAX = 0x03020101; - EBX = ECX = 0; - EDX = 0x0C040843; - } - else - EAX = EBX = ECX = EDX = 0; - break; */ - - case CPU_PENTIUM2D: - if (!EAX) - { - EAX = 0x00000002; - EBX = 0x756e6547; - EDX = 0x49656e69; - ECX = 0x6c65746e; - } - else if (EAX == 1) - { - EAX = CPUID; - EBX = ECX = 0; - EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_SEP | CPUID_FXSR | CPUID_CMOV; - } - else if (EAX == 2) - { - EAX = 0x03020101; - EBX = ECX = 0; - EDX = 0x0C040844; - } - else - EAX = EBX = ECX = EDX = 0; - break; -#endif -#endif - - } -} - -void cpu_RDMSR() -{ - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) - { - case CPU_WINCHIP: - EAX = EDX = 0; - switch (ECX) - { - case 0x02: - EAX = msr.tr1; - break; - case 0x0e: - EAX = msr.tr12; - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x11: - EAX = msr.cesr; - break; - case 0x107: - EAX = msr.fcr; - break; - case 0x108: - EAX = msr.fcr2 & 0xffffffff; - EDX = msr.fcr2 >> 32; - break; - case 0x10a: - EAX = cpu_multi & 3; - break; - } - break; - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) - case CPU_K5: - case CPU_5K86: - case CPU_K6: - EAX = EDX = 0; - switch (ECX) - { - case 0x0e: - EAX = msr.tr12; - break; - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x83: - EAX = ecx83_msr & 0xffffffff; - EDX = ecx83_msr >> 32; - break; - case 0xC0000081: - EAX = star & 0xffffffff; - EDX = star >> 32; - break; - case 0xC0000084: - EAX = sfmask & 0xffffffff; - EDX = sfmask >> 32; - break; - default: - x86gpf(NULL, 0); - break; - } - break; -#endif - - case CPU_PENTIUM: - case CPU_PENTIUMMMX: - EAX = EDX = 0; - switch (ECX) - { - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - } - break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - switch (ECX) - { - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - } - break; -#endif - -#ifdef DEV_BRANCH -#ifdef USE_I686 - case CPU_PENTIUMPRO: - case CPU_PENTIUM2D: - EAX = EDX = 0; - switch (ECX) - { - case 0x10: - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - break; - case 0x17: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpu_type != CPU_PENTIUM2D) goto i686_invalid_rdmsr; - EAX = ecx17_msr & 0xffffffff; - EDX = ecx17_msr >> 32; - break; - case 0x1B: - EAX = apic_base_msr & 0xffffffff; - EDX = apic_base_msr >> 32; - break; - case 0x2A: - EAX = 0xC5800000; - EDX = 0; - break; - case 0x79: - EAX = ecx79_msr & 0xffffffff; - EDX = ecx79_msr >> 32; - break; - case 0x88: case 0x89: case 0x8A: case 0x8B: - EAX = ecx8x_msr[ECX - 0x88] & 0xffffffff; - EDX = ecx8x_msr[ECX - 0x88] >> 32; - break; - case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: - EAX = msr_ia32_pmc[ECX - 0xC1] & 0xffffffff; - EDX = msr_ia32_pmc[ECX - 0xC1] >> 32; - break; - case 0xFE: - EAX = mtrr_cap_msr & 0xffffffff; - EDX = mtrr_cap_msr >> 32; - break; - case 0x116: - EAX = ecx116_msr & 0xffffffff; - EDX = ecx116_msr >> 32; - break; - case 0x118: case 0x119: case 0x11A: case 0x11B: - EAX = ecx11x_msr[ECX - 0x118] & 0xffffffff; - EDX = ecx11x_msr[ECX - 0x118] >> 32; - break; - case 0x11E: - EAX = ecx11e_msr & 0xffffffff; - EDX = ecx11e_msr >> 32; - break; - case 0x174: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; - EAX &= 0xFFFF0000; - EAX |= cs_msr; - break; - case 0x175: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; - EAX = esp_msr; - break; - case 0x176: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_rdmsr; - EAX = eip_msr; - break; - case 0x186: - EAX = ecx186_msr & 0xffffffff; - EDX = ecx186_msr >> 32; - break; - case 0x187: - EAX = ecx187_msr & 0xffffffff; - EDX = ecx187_msr >> 32; - break; - case 0x1E0: - EAX = ecx1e0_msr & 0xffffffff; - EDX = ecx1e0_msr >> 32; - break; - case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F: - if (ECX & 1) - { - EAX = mtrr_physmask_msr[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = mtrr_physmask_msr[(ECX - 0x200) >> 1] >> 32; - } - else - { - EAX = mtrr_physbase_msr[(ECX - 0x200) >> 1] & 0xffffffff; - EDX = mtrr_physbase_msr[(ECX - 0x200) >> 1] >> 32; - } - break; - case 0x250: - EAX = mtrr_fix64k_8000_msr & 0xffffffff; - EDX = mtrr_fix64k_8000_msr >> 32; - break; - case 0x258: - EAX = mtrr_fix16k_8000_msr & 0xffffffff; - EDX = mtrr_fix16k_8000_msr >> 32; - break; - case 0x259: - EAX = mtrr_fix16k_a000_msr & 0xffffffff; - EDX = mtrr_fix16k_a000_msr >> 32; - break; - case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: - EAX = mtrr_fix4k_msr[ECX - 0x268] & 0xffffffff; - EDX = mtrr_fix4k_msr[ECX - 0x268] >> 32; - break; - case 0x277: - EAX = pat_msr & 0xffffffff; - EDX = pat_msr >> 32; - break; - case 0x2FF: - EAX = mtrr_deftype_msr & 0xffffffff; - EDX = mtrr_deftype_msr >> 32; - break; - case 0x570: - EAX = ecx570_msr & 0xffffffff; - EDX = ecx570_msr >> 32; - break; - default: -i686_invalid_rdmsr: - pclog("Invalid MSR read %08X\n", ECX); - x86gpf(NULL, 0); - break; - } - break; -#endif -#endif - } -} - -void cpu_WRMSR() -{ - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) - { - case CPU_WINCHIP: - switch (ECX) - { - case 0x02: - msr.tr1 = EAX & 2; - break; - case 0x0e: - msr.tr12 = EAX & 0x228; - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x11: - msr.cesr = EAX & 0xff00ff; - break; - case 0x107: - msr.fcr = EAX; - if (EAX & (1 << 9)) - cpu_features |= CPU_FEATURE_MMX; - else - cpu_features &= ~CPU_FEATURE_MMX; - if (EAX & (1 << 1)) - cpu_features |= CPU_FEATURE_CX8; - else - cpu_features &= ~CPU_FEATURE_CX8; - if (EAX & (1 << 29)) - CPUID = 0; - else - CPUID = machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpuid_model; - break; - case 0x108: - msr.fcr2 = EAX | ((uint64_t)EDX << 32); - break; - case 0x109: - msr.fcr3 = EAX | ((uint64_t)EDX << 32); - break; - } - break; - -#if defined(DEV_BRANCH) && defined(USE_AMD_K) - case CPU_K5: - case CPU_5K86: - case CPU_K6: - switch (ECX) - { - case 0x0e: - msr.tr12 = EAX & 0x228; - break; - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x83: - ecx83_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0xC0000081: - star = EAX | ((uint64_t)EDX << 32); - break; - case 0xC0000084: - sfmask = EAX | ((uint64_t)EDX << 32); - break; - } - break; -#endif - - case CPU_PENTIUM: - case CPU_PENTIUMMMX: - switch (ECX) - { - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - } - break; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - case CPU_Cx6x86: - case CPU_Cx6x86L: - case CPU_CxGX1: - case CPU_Cx6x86MX: - switch (ECX) - { - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - } - break; -#endif - -#ifdef DEV_BRANCH -#ifdef USE_I686 - case CPU_PENTIUMPRO: - case CPU_PENTIUM2D: - switch (ECX) - { - case 0x10: - tsc = EAX | ((uint64_t)EDX << 32); - break; - case 0x17: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type != CPU_PENTIUM2D) goto i686_invalid_wrmsr; - ecx17_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x1B: - apic_base_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x79: - ecx79_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x88: case 0x89: case 0x8A: case 0x8B: - ecx8x_msr[ECX - 0x88] = EAX | ((uint64_t)EDX << 32); - break; - case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: - msr_ia32_pmc[ECX - 0xC1] = EAX | ((uint64_t)EDX << 32); - break; - case 0xFE: - mtrr_cap_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x116: - ecx116_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x118: case 0x119: case 0x11A: case 0x11B: - ecx11x_msr[ECX - 0x118] = EAX | ((uint64_t)EDX << 32); - break; - case 0x11E: - ecx11e_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x174: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; - cs_msr = EAX & 0xFFFF; - break; - case 0x175: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; - esp_msr = EAX; - break; - case 0x176: - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUMPRO) goto i686_invalid_wrmsr; - eip_msr = EAX; - break; - case 0x186: - ecx186_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x187: - ecx187_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x1E0: - ecx1e0_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207: - case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F: - if (ECX & 1) - mtrr_physmask_msr[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - else - mtrr_physbase_msr[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); - break; - case 0x250: - mtrr_fix64k_8000_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x258: - mtrr_fix16k_8000_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x259: - mtrr_fix16k_a000_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: - mtrr_fix4k_msr[ECX - 0x268] = EAX | ((uint64_t)EDX << 32); - break; - case 0x277: - pat_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x2FF: - mtrr_deftype_msr = EAX | ((uint64_t)EDX << 32); - break; - case 0x570: - ecx570_msr = EAX | ((uint64_t)EDX << 32); - break; - default: -i686_invalid_wrmsr: - pclog("Invalid MSR write %08X: %08X%08X\n", ECX, EDX, EAX); - x86gpf(NULL, 0); - break; - } - break; -#endif -#endif - } -} - -static int cyrix_addr; - -static void cpu_write(uint16_t addr, uint8_t val, void *priv) -{ - if (addr == 0xf0) { - /* Writes to F0 clear FPU error and deassert the interrupt. */ - if (is286) - picintc(1 << 13); - else - nmi = 0; - return; - } else if (addr >= 0xf1) - return; /* FPU stuff */ - - if (!(addr & 1)) - cyrix_addr = val; - else switch (cyrix_addr) - { - case 0xc0: /*CCR0*/ - ccr0 = val; - break; - case 0xc1: /*CCR1*/ - ccr1 = val; - break; - case 0xc2: /*CCR2*/ - ccr2 = val; - break; - case 0xc3: /*CCR3*/ - ccr3 = val; - break; - case 0xe8: /*CCR4*/ - if ((ccr3 & 0xf0) == 0x10) - { - ccr4 = val; -#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_Cx6x86) - { - if (val & 0x80) - CPUID = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpuid_model; - else - CPUID = 0; - } -#endif - } - break; - case 0xe9: /*CCR5*/ - if ((ccr3 & 0xf0) == 0x10) - ccr5 = val; - break; - case 0xea: /*CCR6*/ - if ((ccr3 & 0xf0) == 0x10) - ccr6 = val; - break; - } -} - -static uint8_t cpu_read(uint16_t addr, void *priv) -{ - if (addr >= 0xf0) - return 0xff; /* FPU stuff */ - - if (addr & 1) - { - switch (cyrix_addr) - { - case 0xc0: return ccr0; - case 0xc1: return ccr1; - case 0xc2: return ccr2; - case 0xc3: return ccr3; - case 0xe8: return ((ccr3 & 0xf0) == 0x10) ? ccr4 : 0xff; - case 0xe9: return ((ccr3 & 0xf0) == 0x10) ? ccr5 : 0xff; - case 0xea: return ((ccr3 & 0xf0) == 0x10) ? ccr6 : 0xff; - case 0xfe: return machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cyrix_id & 0xff; - case 0xff: return machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cyrix_id >> 8; - } - if ((cyrix_addr & 0xf0) == 0xc0) return 0xff; - if (cyrix_addr == 0x20 && machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_Cx5x86) return 0xff; - } - return 0xff; -} - - -void -#ifdef USE_DYNAREC -x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f, - const OpFn *dynarec_opcodes, const OpFn *dynarec_opcodes_0f) -{ - x86_opcodes = opcodes; - x86_opcodes_0f = opcodes_0f; - x86_dynarec_opcodes = dynarec_opcodes; - x86_dynarec_opcodes_0f = dynarec_opcodes_0f; -} -#else -x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f) -{ - x86_opcodes = opcodes; - x86_opcodes_0f = opcodes_0f; -} -#endif - - -void -cpu_update_waitstates(void) -{ - cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; - - if (is486) - cpu_prefetch_width = 16; - else - cpu_prefetch_width = cpu_16bitbus ? 2 : 4; - - if (cpu_cache_int_enabled) - { - /* Disable prefetch emulation */ - cpu_prefetch_cycles = 0; - } - else if (cpu_waitstates && (cpu_s->cpu_type >= CPU_286 && cpu_s->cpu_type <= CPU_386DX)) - { - /* Waitstates override */ - cpu_prefetch_cycles = cpu_waitstates+1; - cpu_cycles_read = cpu_waitstates+1; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); - cpu_cycles_write = cpu_waitstates+1; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * (cpu_waitstates+1); - } - else if (cpu_cache_ext_enabled) - { - /* Use cache timings */ - cpu_prefetch_cycles = cpu_s->cache_read_cycles; - cpu_cycles_read = cpu_s->cache_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_read_cycles; - cpu_cycles_write = cpu_s->cache_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->cache_write_cycles; - } - else - { - /* Use memory timings */ - cpu_prefetch_cycles = cpu_s->mem_read_cycles; - cpu_cycles_read = cpu_s->mem_read_cycles; - cpu_cycles_read_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_read_cycles; - cpu_cycles_write = cpu_s->mem_write_cycles; - cpu_cycles_write_l = (cpu_16bitbus ? 2 : 1) * cpu_s->mem_write_cycles; - } - if (is486) - cpu_prefetch_cycles = (cpu_prefetch_cycles * 11) / 16; - cpu_mem_prefetch_cycles = cpu_prefetch_cycles; - if (cpu_s->rspeed <= 8000000) - cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles; -} diff --git a/src/cpu/cpu_table.c b/src/cpu/cpu_table.c deleted file mode 100644 index a0e77f414..000000000 --- a/src/cpu/cpu_table.c +++ /dev/null @@ -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, - * leilei, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 leilei. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - */ -#include -#include -#include -#include -#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 diff --git a/src/cpu/x86.h b/src/cpu/x86.h deleted file mode 100644 index cf664a8b1..000000000 --- a/src/cpu/x86.h +++ /dev/null @@ -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 diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h deleted file mode 100644 index 12a7e96bc..000000000 --- a/src/cpu/x86_ops.h +++ /dev/null @@ -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, - * Sarah Walker, - * Miran Grca, - * - * 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*/ diff --git a/src/cpu/x86_ops_arith.h b/src/cpu/x86_ops_arith.h deleted file mode 100644 index 80a0da788..000000000 --- a/src/cpu/x86_ops_arith.h +++ /dev/null @@ -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; -} - diff --git a/src/cpu/x86_ops_arith_ex.h b/src/cpu/x86_ops_arith_ex.h deleted file mode 100644 index cc4fcd7c3..000000000 --- a/src/cpu/x86_ops_arith_ex.h +++ /dev/null @@ -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; -} - diff --git a/src/cpu/x86_ops_atomic.h b/src/cpu/x86_ops_atomic.h deleted file mode 100644 index c490d747a..000000000 --- a/src/cpu/x86_ops_atomic.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_bit.h b/src/cpu/x86_ops_bit.h deleted file mode 100644 index 42d9aa4aa..000000000 --- a/src/cpu/x86_ops_bit.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_i686.h b/src/cpu/x86_ops_i686.h deleted file mode 100644 index 6d4cf7484..000000000 --- a/src/cpu/x86_ops_i686.h +++ /dev/null @@ -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, - * 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; -} diff --git a/src/cpu/x86_ops_jump.h b/src/cpu/x86_ops_jump.h deleted file mode 100644 index 6eb9862af..000000000 --- a/src/cpu/x86_ops_jump.h +++ /dev/null @@ -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; -} - diff --git a/src/cpu/x86_ops_mmx.h b/src/cpu/x86_ops_mmx.h deleted file mode 100644 index 107710f77..000000000 --- a/src/cpu/x86_ops_mmx.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_mmx_arith.h b/src/cpu/x86_ops_mmx_arith.h deleted file mode 100644 index e8e1f31e5..000000000 --- a/src/cpu/x86_ops_mmx_arith.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_mmx_mov.h b/src/cpu/x86_ops_mmx_mov.h deleted file mode 100644 index a742941ea..000000000 --- a/src/cpu/x86_ops_mmx_mov.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_mmx_pack.h b/src/cpu/x86_ops_mmx_pack.h deleted file mode 100644 index 170aa0e42..000000000 --- a/src/cpu/x86_ops_mmx_pack.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_mmx_shift.h b/src/cpu/x86_ops_mmx_shift.h deleted file mode 100644 index edfe16276..000000000 --- a/src/cpu/x86_ops_mmx_shift.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_mov_ctrl.h b/src/cpu/x86_ops_mov_ctrl.h deleted file mode 100644 index becb0e095..000000000 --- a/src/cpu/x86_ops_mov_ctrl.h +++ /dev/null @@ -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; -} - diff --git a/src/cpu/x86_ops_pmode.h b/src/cpu/x86_ops_pmode.h deleted file mode 100644 index cdf89d98d..000000000 --- a/src/cpu/x86_ops_pmode.h +++ /dev/null @@ -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); -} diff --git a/src/cpu/x86_ops_stack.h b/src/cpu/x86_ops_stack.h deleted file mode 100644 index 20b0aa766..000000000 --- a/src/cpu/x86_ops_stack.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_string.h b/src/cpu/x86_ops_string.h deleted file mode 100644 index 41e368cc7..000000000 --- a/src/cpu/x86_ops_string.h +++ /dev/null @@ -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; -} diff --git a/src/cpu/x86_ops_xchg.h b/src/cpu/x86_ops_xchg.h deleted file mode 100644 index 3880f70e7..000000000 --- a/src/cpu/x86_ops_xchg.h +++ /dev/null @@ -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) diff --git a/src/cpu/x86seg.c b/src/cpu/x86seg.c index d2dd5e8ad..ced052ea0 100644 --- a/src/cpu/x86seg.c +++ b/src/cpu/x86seg.c @@ -24,13 +24,13 @@ #include #include #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)) { diff --git a/src/cpu/x87.c b/src/cpu/x87.c deleted file mode 100644 index abc2f48a4..000000000 --- a/src/cpu/x87.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include -#include -#define fplog 0 -#include -#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 diff --git a/src/cpu/x87.h b/src/cpu/x87.h deleted file mode 100644 index 6d2cb3ca9..000000000 --- a/src/cpu/x87.h +++ /dev/null @@ -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) diff --git a/src/cpu_common/386.c b/src/cpu_common/386.c new file mode 100644 index 000000000..416f9577e --- /dev/null +++ b/src/cpu_common/386.c @@ -0,0 +1,335 @@ +#include +#include +#include +#include +#include +#include +#include +#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(); + } + } +} diff --git a/src/cpu_new/386_common.c b/src/cpu_common/386_common.c similarity index 93% rename from src/cpu_new/386_common.c rename to src/cpu_common/386_common.c index 32b65e0bf..cb140c41a 100644 --- a/src/cpu_new/386_common.c +++ b/src/cpu_common/386_common.c @@ -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)); } diff --git a/src/cpu/386_common.h b/src/cpu_common/386_common.h similarity index 77% rename from src/cpu/386_common.h rename to src/cpu_common/386_common.h index 428bf3118..2ab8157a2 100644 --- a/src/cpu/386_common.h +++ b/src/cpu_common/386_common.h @@ -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 diff --git a/src/cpu/386_dynarec.c b/src/cpu_common/386_dynarec - Cópia (2).c similarity index 85% rename from src/cpu/386_dynarec.c rename to src/cpu_common/386_dynarec - Cópia (2).c index 7a26ae37d..421381dd3 100644 --- a/src/cpu/386_dynarec.c +++ b/src/cpu_common/386_dynarec - Cópia (2).c @@ -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; diff --git a/src/cpu_new/386_dynarec.c b/src/cpu_common/386_dynarec - Cópia.c similarity index 83% rename from src/cpu_new/386_dynarec.c rename to src/cpu_common/386_dynarec - Cópia.c index 0081aceb8..75219e86a 100644 --- a/src/cpu_new/386_dynarec.c +++ b/src/cpu_common/386_dynarec - Cópia.c @@ -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); } } diff --git a/src/cpu_common/386_dynarec.c b/src/cpu_common/386_dynarec.c new file mode 100644 index 000000000..b03f723c1 --- /dev/null +++ b/src/cpu_common/386_dynarec.c @@ -0,0 +1,1007 @@ +#include +#include +#include +#include +#include +#include +#include +#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) + { +#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; + + 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); + } + +#ifndef USE_NEW_DYNAREC + if (!use32) cpu_state.pc &= 0xffff; +#endif + + 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); +#ifdef USE_NEW_DYNAREC + codeblock_t *block = &codeblock[codeblock_hash[hash]]; +#else + codeblock_t *block = codeblock_hash[hash]; +#endif + int valid_block = 0; +#ifdef USE_NEW_DYNAREC + + if (!cpu_state.abrt) +#else + trap = 0; + + 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); +#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)) +#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)) + { +#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; +#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)); +#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; + else if (block->page_mask2 & *block->dirty_mask2) + { +#ifdef USE_NEW_DYNAREC + codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; +#else + 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; + if (block->flags & CODEBLOCK_BYTE_MASK) + block->flags |= CODEBLOCK_NO_IMMEDIATES; + else + block->flags |= CODEBLOCK_BYTE_MASK; + } + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) +#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)) +#else + if (valid_block && block->was_recompiled) +#endif + { + void (*code)() = (void *)&block->data[BLOCK_START]; + +#ifndef USE_NEW_DYNAREC + codeblock_hash[hash] = block; +#endif + + 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; +#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) + { +#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.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; + } + +#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) + 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*/ +#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; +#else + start_pc = cpu_state.pc; +#endif + + 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; + + 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; + } + +#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) + 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(); + } +#ifdef USE_NEW_DYNAREC + else + cpu_state.oldpc = cpu_state.pc; +#endif + } + + 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; +#ifndef USE_NEW_DYNAREC + CS = oldcs; +#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) + { +#ifdef USE_NEW_DYNAREC + trap = 0; +#endif + 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; +#ifndef USE_NEW_DYNAREC + oldcs = CS; +#endif + 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; +#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); + } +} +#endif diff --git a/src/cpu_common/386_dynarec.c.temp b/src/cpu_common/386_dynarec.c.temp new file mode 100644 index 000000000..78130f3c0 --- /dev/null +++ b/src/cpu_common/386_dynarec.c.temp @@ -0,0 +1,900 @@ +#include +#include +#include +#include +#include +#include +#include +#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 diff --git a/src/cpu/386_dynarec_ops.c b/src/cpu_common/386_dynarec_ops.c similarity index 90% rename from src/cpu/386_dynarec_ops.c rename to src/cpu_common/386_dynarec_ops.c index aa4784ba8..42edfbef5 100644 --- a/src/cpu/386_dynarec_ops.c +++ b/src/cpu_common/386_dynarec_ops.c @@ -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" diff --git a/src/cpu_new/386_ops.h b/src/cpu_common/386_ops.h similarity index 99% rename from src/cpu_new/386_ops.h rename to src/cpu_common/386_ops.h index b3d331423..8459607ff 100644 --- a/src/cpu_new/386_ops.h +++ b/src/cpu_common/386_ops.h @@ -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] = { diff --git a/src/cpu/808x.c b/src/cpu_common/808x.c similarity index 98% rename from src/cpu/808x.c rename to src/cpu_common/808x.c index bf028eeaa..ede1412cd 100644 --- a/src/cpu/808x.c +++ b/src/cpu_common/808x.c @@ -23,17 +23,18 @@ #include #include #include + #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++; diff --git a/src/cpu_common/codegen_public.h b/src/cpu_common/codegen_public.h new file mode 100644 index 000000000..e5ca4b33e --- /dev/null +++ b/src/cpu_common/codegen_public.h @@ -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, + * + * 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 diff --git a/src/cpu_new/cpu.c b/src/cpu_common/cpu.c similarity index 76% rename from src/cpu_new/cpu.c rename to src/cpu_common/cpu.c index 26b790dc4..43e8a7adb 100644 --- a/src/cpu_new/cpu.c +++ b/src/cpu_common/cpu.c @@ -38,20 +38,21 @@ * Boston, MA 02111-1307 * USA. */ +#include #include #include #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../device.h" -#include "../machine/machine.h" -#include "../io.h" +#include "device.h" +#include "machine.h" +#include "86box_io.h" #include "x86_ops.h" -#include "../mem.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pci.h" +#include "mem.h" +#include "nmi.h" +#include "pic.h" +#include "pci.h" #ifdef USE_DYNAREC # include "codegen.h" #endif @@ -103,8 +104,10 @@ const OpFn *x86_dynarec_opcodes_df_a16; const OpFn *x86_dynarec_opcodes_df_a32; const OpFn *x86_dynarec_opcodes_REPE; const OpFn *x86_dynarec_opcodes_REPNE; +#ifdef USE_NEW_DYNAREC const OpFn *x86_dynarec_opcodes_3DNOW; #endif +#endif const OpFn *x86_opcodes; const OpFn *x86_opcodes_0f; @@ -134,6 +137,7 @@ uint32_t smbase = 0x30000; CPU *cpu_s; int cpu_effective; int cpu_multi; +double cpu_dmulti; int cpu_16bitbus; int cpu_busspeed; int cpu_cyrix_alignment; @@ -153,6 +157,7 @@ uint32_t cpu_features; int is286, is386, is486 = 1, + is486sx, is486dx, is486sx2, is486dx2, isdx4, cpu_iscyrix, isibmcpu, israpidcad, @@ -168,11 +173,6 @@ uint64_t pmc[2] = {0, 0}; uint16_t temp_seg_data[4] = {0, 0, 0, 0}; -#if defined(DEV_BRANCH) && defined(USE_I686) -uint16_t cs_msr = 0; -uint32_t esp_msr = 0; -uint32_t eip_msr = 0; -uint64_t apic_base_msr = 0; uint64_t mtrr_cap_msr = 0; uint64_t mtrr_physbase_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint64_t mtrr_physmask_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -180,8 +180,14 @@ uint64_t mtrr_fix64k_8000_msr = 0; uint64_t mtrr_fix16k_8000_msr = 0; uint64_t mtrr_fix16k_a000_msr = 0; uint64_t mtrr_fix4k_msr[8] = {0, 0, 0, 0, 0, 0, 0, 0}; -uint64_t pat_msr = 0; uint64_t mtrr_deftype_msr = 0; + +#if defined(DEV_BRANCH) && defined(USE_I686) +uint16_t cs_msr = 0; +uint32_t esp_msr = 0; +uint32_t eip_msr = 0; +uint64_t apic_base_msr = 0; +uint64_t pat_msr = 0; uint64_t msr_ia32_pmc[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint64_t ecx17_msr = 0; uint64_t ecx79_msr = 0; @@ -195,9 +201,21 @@ uint64_t ecx1e0_msr = 0; uint64_t ecx570_msr = 0; #endif +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) uint64_t ecx83_msr = 0; /* AMD K5 and K6 MSR's. */ -uint64_t star = 0; /* These are K6-only. */ -uint64_t sfmask = 0; +#ifdef USE_NEW_DYNAREC +uint64_t star = 0; /* AMD K6-2+. */ +#endif + +#ifdef USE_NEW_DYNAREC +uint64_t amd_efer = 0, amd_whcr = 0, + amd_uwccr = 0, amd_epmr = 0, /* AMD K6-2+ registers. */ + amd_psor = 0, amd_pfir = 0, + amd_l2aar = 0; +#else +uint64_t amd_efer = 0, amd_whcr = 0; +#endif +#endif int timing_rr; int timing_mr, timing_mrl; @@ -253,27 +271,40 @@ cpu_set(void) cpu_manufacturer = 0; cpu = 0; } - + cpu_effective = cpu; cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective]; cpu_alt_reset = 0; - CPUID = cpu_s->cpuid_model; - is8086 = (cpu_s->cpu_type > CPU_8088); - is286 = (cpu_s->cpu_type >= CPU_286); - is386 = (cpu_s->cpu_type >= CPU_386SX); - isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); - israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); - is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); - is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); - hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); - cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); + CPUID = cpu_s->cpuid_model; + is8086 = (cpu_s->cpu_type > CPU_8088); + is286 = (cpu_s->cpu_type >= CPU_286); + is386 = (cpu_s->cpu_type >= CPU_386SX); + isibmcpu = (cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL); + israpidcad = (cpu_s->cpu_type == CPU_RAPIDCAD); + is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_RAPIDCAD || cpu_s->cpu_type == CPU_IBM486SLC || cpu_s->cpu_type == CPU_IBM486BL ); + is486sx = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type < CPU_i486SX2); + is486sx2 = (cpu_s->cpu_type >= CPU_i486SX2) && (cpu_s->cpu_type < CPU_i486DX); + is486dx = (cpu_s->cpu_type >= CPU_i486DX) && (cpu_s->cpu_type < CPU_i486DX2); + is486dx2 = (cpu_s->cpu_type >= CPU_iDX4) && (cpu_s->cpu_type < CPU_WINCHIP); + isdx4 = (cpu_s->cpu_type >= CPU_i486DX2) && (cpu_s->cpu_type < CPU_iDX4); + is_pentium = (cpu_s->cpu_type >= CPU_WINCHIP); + hasfpu = (cpu_s->cpu_type >= CPU_i486DX) || (cpu_s->cpu_type == CPU_RAPIDCAD); +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) + cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1); +#else + cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86); +#endif + cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC ); - if (cpu_s->multi) { - cpu_busspeed = cpu_s->rspeed / cpu_s->multi; - } - cpu_multi = cpu_s->multi; + + if (cpu_s->multi) + cpu_busspeed = cpu_s->rspeed / cpu_s->multi; + else + cpu_busspeed = cpu_s->rspeed; + cpu_multi = (int) ceil(cpu_s->multi); + cpu_dmulti = cpu_s->multi; ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0; if ((cpu_s->cpu_type == CPU_8088) || (cpu_s->cpu_type == CPU_8086) || @@ -291,16 +322,15 @@ cpu_set(void) else cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000; - if (cpu_s->pci_speed) - { - pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed; - pci_burst_time = cpu_s->rspeed / cpu_s->pci_speed; - } - else - { - pci_nonburst_time = 4; - pci_burst_time = 1; - } + if (cpu_busspeed < 42500000) + cpu_pci_speed = cpu_busspeed; + else if ((cpu_busspeed > 42500000) && (cpu_busspeed < 84000000)) + cpu_pci_speed = cpu_busspeed / 2; + else + cpu_pci_speed = cpu_busspeed / 3; + + pci_burst_time = cpu_s->rspeed / cpu_pci_speed; + pci_nonburst_time = 4 * pci_burst_time; if (cpu_iscyrix) io_sethandler(0x0022, 0x0002, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); @@ -311,7 +341,7 @@ cpu_set(void) io_sethandler(0x00f0, 0x000f, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); else io_removehandler(0x00f0, 0x000f, cpu_read, NULL, NULL, cpu_write, NULL, NULL, NULL); - + #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f); #else @@ -323,8 +353,10 @@ cpu_set(void) #ifdef USE_DYNAREC x86_dynarec_opcodes_REPE = dynarec_ops_REPE; x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE; +#ifdef USE_NEW_DYNAREC x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW; #endif +#endif #ifdef USE_DYNAREC if (hasfpu) @@ -486,7 +518,7 @@ cpu_set(void) timing_jmp_pm = 23; timing_jmp_pm_gate = 38; break; - + case CPU_IBM386SLC: case CPU_386SX: timing_rr = 2; /*register dest - register src*/ @@ -549,7 +581,7 @@ cpu_set(void) timing_jmp_pm = 27; timing_jmp_pm_gate = 45; break; - + case CPU_IBM486SLC: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); @@ -586,6 +618,7 @@ cpu_set(void) timing_jmp_pm_gate = 32; timing_misaligned = 3; break; + case CPU_IBM486BL: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); @@ -739,8 +772,11 @@ cpu_set(void) case CPU_iDX4: cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME; cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME; + /*FALLTHROUGH*/ case CPU_i486SX: + case CPU_i486SX2: case CPU_i486DX: + case CPU_i486DX2: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else @@ -778,7 +814,11 @@ cpu_set(void) break; case CPU_Am486SX: + case CPU_Am486SX2: case CPU_Am486DX: + case CPU_Am486DX2: + case CPU_Am486DX4: + case CPU_Am5x86: /*AMD timing identical to Intel*/ #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); @@ -818,6 +858,7 @@ cpu_set(void) case CPU_Cx486S: case CPU_Cx486DX: + case CPU_Cx486DX2: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_486_0f, dynarec_ops_386, dynarec_ops_486_0f); #else @@ -936,6 +977,7 @@ cpu_set(void) cpu_cyrix_alignment = 1; break; +#ifdef USE_NEW_DYNAREC case CPU_WINCHIP2: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); @@ -975,8 +1017,11 @@ cpu_set(void) timing_jmp_pm_gate = 17; timing_misaligned = 2; cpu_cyrix_alignment = 1; +#ifdef USE_DYNAREC codegen_timing_set(&codegen_timing_winchip2); +#endif break; +#endif case CPU_PENTIUM: #ifdef USE_DYNAREC @@ -1064,6 +1109,7 @@ cpu_set(void) #endif break; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) case CPU_Cx6x86: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); @@ -1232,13 +1278,15 @@ cpu_set(void) #endif ccr4 = 0x80; break; +#endif +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) case CPU_K5: case CPU_5K86: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else - x86_setopcodes(ops_386, ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f); #endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ @@ -1272,16 +1320,16 @@ cpu_set(void) cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; -#ifdef USE_DYNAREC +#if defined(USE_NEW_DYNAREC) && defined(USE_DYNAREC) codegen_timing_set(&codegen_timing_k6); #endif break; case CPU_K6: #ifdef USE_DYNAREC - x86_setopcodes(ops_386, ops_k6_0f, dynarec_ops_386, dynarec_ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f); #else - x86_setopcodes(ops_386, ops_k6_0f); + x86_setopcodes(ops_386, ops_pentiummmx_0f); #endif timing_rr = 1; /*register dest - register src*/ timing_rm = 2; /*register dest - memory src*/ @@ -1316,11 +1364,18 @@ cpu_set(void) msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC +#ifdef USE_NEW_DYNAREC codegen_timing_set(&codegen_timing_k6); +#else + codegen_timing_set(&codegen_timing_pentium); +#endif #endif break; +#endif +#ifdef USE_NEW_DYNAREC case CPU_K6_2: + case CPU_K6_2C: case CPU_K6_3: case CPU_K6_2P: case CPU_K6_3P: @@ -1363,6 +1418,7 @@ cpu_set(void) cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE; codegen_timing_set(&codegen_timing_k6); break; +#endif #if defined(DEV_BRANCH) && defined(USE_I686) case CPU_PENTIUMPRO: @@ -1384,42 +1440,46 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC +#ifdef USE_NEW_DYNAREC + codegen_timing_set(&codegen_timing_k6); +#else codegen_timing_set(&codegen_timing_686); +#endif #endif break; -#if 0 case CPU_PENTIUM2: #ifdef USE_DYNAREC x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); @@ -1439,41 +1499,45 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; #ifdef USE_DYNAREC +#ifdef USE_NEW_DYNAREC + codegen_timing_set(&codegen_timing_k6); +#else codegen_timing_set(&codegen_timing_686); #endif - break; #endif + break; case CPU_PENTIUM2D: #ifdef USE_DYNAREC @@ -1494,41 +1558,89 @@ cpu_set(void) x86_opcodes_df_a16 = ops_fpu_686_df_a16; x86_opcodes_df_a32 = ops_fpu_686_df_a32; timing_rr = 1; /*register dest - register src*/ - timing_rm = 1; /*register dest - memory src*/ - timing_mr = 1; /*memory dest - register src*/ - timing_mm = 1; - timing_rml = 1; /*register dest - memory src long*/ - timing_mrl = 1; /*memory dest - register src long*/ - timing_mml = 1; + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; timing_bt = 0; /*branch taken*/ timing_bnt = 1; /*branch not taken*/ - timing_int_rm = 9; - timing_int_v86 = 46; - timing_int_pm = 21; - timing_int_pm_outer = 32; + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; timing_iret_rm = 7; - timing_iret_v86 = 26; + timing_iret_v86 = 27; /*unknown*/ timing_iret_pm = 10; - timing_iret_pm_outer = 26; - timing_call_rm = 3; + timing_iret_pm_outer = 27; + timing_call_rm = 4; timing_call_pm = 4; - timing_call_pm_gate = 15; - timing_call_pm_gate_inner = 26; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; timing_retf_rm = 4; timing_retf_pm = 4; timing_retf_pm_outer = 23; - timing_jmp_rm = 1; - timing_jmp_pm = 4; - timing_jmp_pm_gate = 14; - timing_misaligned = 2; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX; msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE | CR4_OSFXSR; #ifdef USE_DYNAREC +#ifdef USE_NEW_DYNAREC + codegen_timing_set(&codegen_timing_k6); +#else codegen_timing_set(&codegen_timing_686); +#endif #endif break; #endif + case CPU_CYRIX3S: +#ifdef USE_DYNAREC + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); +#else + x86_setopcodes(ops_386, ops_winchip2_0f); +#endif + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 2; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 2; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 3-1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; + /*unknown*/ + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; + timing_misaligned = 2; + cpu_cyrix_alignment = 1; +#ifdef USE_DYNAREC + codegen_timing_set(&codegen_timing_winchip); +#endif + break; default: fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type); @@ -1557,6 +1669,7 @@ cpu_CPUID(void) { case CPU_RAPIDCAD: case CPU_i486DX: + case CPU_i486DX2: if (!EAX) { EAX = 0x00000001; @@ -1593,6 +1706,7 @@ cpu_CPUID(void) break; case CPU_Am486SX: + case CPU_Am486SX2: if (!EAX) { EAX = 1; @@ -1610,6 +1724,9 @@ cpu_CPUID(void) break; case CPU_Am486DX: + case CPU_Am486DX2: + case CPU_Am486DX4: + case CPU_Am5x86: if (!EAX) { EAX = 1; @@ -1658,6 +1775,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; +#ifdef USE_NEW_DYNAREC case CPU_WINCHIP2: switch (EAX) { @@ -1677,7 +1795,7 @@ cpu_CPUID(void) } break; case 1: - EAX = 0x580; + EAX = CPUID; EBX = ECX = 0; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) @@ -1689,7 +1807,7 @@ cpu_CPUID(void) EAX = 0x80000005; break; case 0x80000001: - EAX = 0x580; + EAX = CPUID; EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; if (cpu_has_feature(CPU_FEATURE_CX8)) EDX |= CPUID_CMPXCHG8B; @@ -1717,6 +1835,7 @@ cpu_CPUID(void) break; } break; +#endif case CPU_PENTIUM: if (!EAX) @@ -1736,6 +1855,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) case CPU_K5: if (!EAX) { @@ -1867,8 +1987,11 @@ cpu_CPUID(void) else EAX = EBX = ECX = EDX = 0; break; +#endif +#ifdef USE_NEW_DYNAREC case CPU_K6_2: + case CPU_K6_2C: switch (EAX) { case 0: @@ -2027,6 +2150,7 @@ cpu_CPUID(void) break; } break; +#endif case CPU_PENTIUMMMX: if (!EAX) @@ -2047,6 +2171,7 @@ cpu_CPUID(void) break; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) case CPU_Cx6x86: if (!EAX) { @@ -2122,6 +2247,7 @@ cpu_CPUID(void) else EAX = EBX = ECX = EDX = 0; break; +#endif #ifdef DEV_BRANCH #ifdef USE_I686 @@ -2146,7 +2272,7 @@ cpu_CPUID(void) EAX = EBX = ECX = EDX = 0; break; - /* case CPU_PENTIUM2: + case CPU_PENTIUM2: if (!EAX) { EAX = 0x00000002; @@ -2168,7 +2294,7 @@ cpu_CPUID(void) } else EAX = EBX = ECX = EDX = 0; - break; */ + break; case CPU_PENTIUM2D: if (!EAX) @@ -2195,16 +2321,118 @@ cpu_CPUID(void) break; #endif #endif - + case CPU_CYRIX3S: + switch (EAX) + { + case 0: + EAX = 1; + if (msr.fcr2 & (1 << 14)) + { + EBX = msr.fcr3 >> 32; + ECX = msr.fcr3 & 0xffffffff; + EDX = msr.fcr2 >> 32; + } + else + { + EBX = 0x746e6543; /*CentaurHauls*/ + ECX = 0x736c7561; + EDX = 0x48727561; + } + break; + case 1: + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000005; + break; + case 0x80000001: + EAX = CPUID; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + if (cpu_has_feature(CPU_FEATURE_3DNOW)) + EDX |= CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + EAX = 0x20414956; /*VIA Samuel*/ + EBX = 0x756d6153; + ECX = 0x00006c65; + EDX = 0x00000000; + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x08800880; /*TLBs*/ + ECX = 0x40040120; /*L1 data cache*/ + EDX = 0x40020120; /*L1 instruction cache*/ + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; } } +void cpu_ven_reset(void) +{ +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) + { + case CPU_K5: + case CPU_5K86: + case CPU_K6: + amd_efer = amd_whcr = 0ULL; + break; +#ifdef USE_NEW_DYNAREC + case CPU_K6_2: + amd_efer = amd_whcr = 0ULL; + star = 0ULL; + break; + case CPU_K6_2C: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x018cULL; + amd_uwccr = 0ULL; + break; + case CPU_K6_3: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x008cULL; + amd_uwccr = 0ULL; + amd_pfir = amd_l2aar = 0ULL; + break; + case CPU_K6_2P: + case CPU_K6_3P: + amd_efer = 2ULL; + amd_whcr = star = 0ULL; + amd_psor = 0x008cULL; + amd_uwccr = 0ULL; + amd_pfir = amd_l2aar = 0ULL; + amd_epmr = 0ULL; + break; +#endif + } +#endif +} + void cpu_RDMSR() { switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { case CPU_WINCHIP: +#ifdef USE_NEW_DYNAREC case CPU_WINCHIP2: +#endif EAX = EDX = 0; switch (ECX) { @@ -2233,41 +2461,295 @@ void cpu_RDMSR() break; } break; - - case CPU_K5: - case CPU_5K86: - case CPU_K6: - case CPU_K6_2: - case CPU_K6_3: - case CPU_K6_2P: - case CPU_K6_3P: + + case CPU_CYRIX3S: EAX = EDX = 0; switch (ECX) { - case 0x0e: - EAX = msr.tr12; - break; case 0x10: EAX = tsc & 0xffffffff; EDX = tsc >> 32; break; - case 0x83: + case 0x2a: + if (cpu_dmulti == 3) + EAX = ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 3.5) + EAX = ((0 << 25) | (1 << 24) | (0 << 23) | (1 << 22)); + else if (cpu_dmulti == 4) + EAX = ((0 << 25) | (0 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 4.5) + EAX = ((0 << 25) | (1 << 24) | (1 << 23) | (0 << 22)); + else if (cpu_dmulti == 5) + EAX = 0; + else if (cpu_dmulti == 5.5) + EAX = ((0 << 25) | (1 << 24) | (0 << 23) | (0 << 22)); + else if (cpu_dmulti == 6) + EAX = ((1 << 25) | (0 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 6.5) + EAX = ((1 << 25) | (1 << 24) | (1 << 23) | (1 << 22)); + else if (cpu_dmulti == 7) + EAX = ((1 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + else + EAX = ((0 << 25) | (0 << 24) | (0 << 23) | (1 << 22)); + break; + case 0x1107: + EAX = msr.fcr; + break; + case 0x1108: + EAX = msr.fcr2 & 0xffffffff; + EDX = msr.fcr2 >> 32; + break; + case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207: + case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F: + if (ECX & 1) + { + EAX = mtrr_physmask_msr[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = mtrr_physmask_msr[(ECX - 0x200) >> 1] >> 32; + } + else + { + EAX = mtrr_physbase_msr[(ECX - 0x200) >> 1] & 0xffffffff; + EDX = mtrr_physbase_msr[(ECX - 0x200) >> 1] >> 32; + } + break; + case 0x250: + EAX = mtrr_fix64k_8000_msr & 0xffffffff; + EDX = mtrr_fix64k_8000_msr >> 32; + break; + case 0x258: + EAX = mtrr_fix16k_8000_msr & 0xffffffff; + EDX = mtrr_fix16k_8000_msr >> 32; + break; + case 0x259: + EAX = mtrr_fix16k_a000_msr & 0xffffffff; + EDX = mtrr_fix16k_a000_msr >> 32; + break; + case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: + EAX = mtrr_fix4k_msr[ECX - 0x268] & 0xffffffff; + EDX = mtrr_fix4k_msr[ECX - 0x268] >> 32; + break; + case 0x2FF: + EAX = mtrr_deftype_msr & 0xffffffff; + EDX = mtrr_deftype_msr >> 32; + break; + } + break; + +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) + case CPU_K5: + case CPU_5K86: + case CPU_K6: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: EAX = ecx83_msr & 0xffffffff; EDX = ecx83_msr >> 32; break; - case 0xC0000081: - EAX = star & 0xffffffff; - EDX = star >> 32; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; break; - case 0xC0000084: - EAX = sfmask & 0xffffffff; - EDX = sfmask >> 32; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; break; default: x86gpf(NULL, 0); break; } break; +#endif + +#ifdef USE_NEW_DYNAREC + case CPU_K6_2: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2C: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_3: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + case 0xC0000089: + EAX = amd_l2aar & 0xffffffff; + EDX = amd_l2aar >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2P: + case CPU_K6_3P: + EAX = EDX = 0; + switch (ECX) + { + case 0x0000000e: + EAX = msr.tr12; + break; + case 0x00000010: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + case 0x00000083: + EAX = ecx83_msr & 0xffffffff; + EDX = ecx83_msr >> 32; + break; + case 0xC0000080: + EAX = amd_efer & 0xffffffff; + EDX = amd_efer >> 32; + break; + case 0xC0000081: + EAX = star & 0xffffffff; + EDX = star >> 32; + break; + case 0xC0000082: + EAX = amd_whcr & 0xffffffff; + EDX = amd_whcr >> 32; + break; + case 0xC0000085: + EAX = amd_uwccr & 0xffffffff; + EDX = amd_uwccr >> 32; + break; + case 0xC0000086: + EAX = amd_epmr & 0xffffffff; + EDX = amd_epmr >> 32; + break; + case 0xC0000087: + EAX = amd_psor & 0xffffffff; + EDX = amd_psor >> 32; + break; + case 0xC0000088: + EAX = amd_pfir & 0xffffffff; + EDX = amd_pfir >> 32; + break; + case 0xC0000089: + EAX = amd_l2aar & 0xffffffff; + EDX = amd_l2aar >> 32; + break; + default: + x86gpf(NULL, 0); + break; + } + break; +#endif case CPU_PENTIUM: case CPU_PENTIUMMMX: @@ -2280,6 +2762,7 @@ void cpu_RDMSR() break; } break; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -2292,10 +2775,12 @@ void cpu_RDMSR() break; } break; +#endif #ifdef DEV_BRANCH #ifdef USE_I686 case CPU_PENTIUMPRO: + case CPU_PENTIUM2: case CPU_PENTIUM2D: EAX = EDX = 0; switch (ECX) @@ -2413,6 +2898,7 @@ void cpu_RDMSR() break; default: i686_invalid_rdmsr: + // pclog("RDMSR: Invalid MSR: %08X\n", ECX); x86gpf(NULL, 0); break; } @@ -2424,10 +2910,16 @@ i686_invalid_rdmsr: void cpu_WRMSR() { +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) + uint64_t temp; +#endif + switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type) { case CPU_WINCHIP: +#ifdef USE_NEW_DYNAREC case CPU_WINCHIP2: +#endif switch (ECX) { case 0x02: @@ -2452,10 +2944,12 @@ void cpu_WRMSR() cpu_features |= CPU_FEATURE_CX8; else cpu_features &= ~CPU_FEATURE_CX8; +#ifdef USE_NEW_DYNAREC if ((EAX & (1 << 20)) && machines[machine].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2) cpu_features |= CPU_FEATURE_3DNOW; else cpu_features &= ~CPU_FEATURE_3DNOW; +#endif if (EAX & (1 << 29)) CPUID = 0; else @@ -2468,13 +2962,198 @@ void cpu_WRMSR() msr.fcr3 = EAX | ((uint64_t)EDX << 32); break; } + break; + case CPU_CYRIX3S: + switch (ECX) + { + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x1107: + msr.fcr = EAX; + if (EAX & (1 << 1)) + cpu_features |= CPU_FEATURE_CX8; + else + cpu_features &= ~CPU_FEATURE_CX8; + break; + case 0x1108: + msr.fcr2 = EAX | ((uint64_t)EDX << 32); + break; + case 0x1109: + msr.fcr3 = EAX | ((uint64_t)EDX << 32); + break; + case 0x200: case 0x201: case 0x202: case 0x203: case 0x204: case 0x205: case 0x206: case 0x207: + case 0x208: case 0x209: case 0x20A: case 0x20B: case 0x20C: case 0x20D: case 0x20E: case 0x20F: + if (ECX & 1) + mtrr_physmask_msr[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); + else + mtrr_physbase_msr[(ECX - 0x200) >> 1] = EAX | ((uint64_t)EDX << 32); + break; + case 0x250: + mtrr_fix64k_8000_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0x258: + mtrr_fix16k_8000_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0x259: + mtrr_fix16k_a000_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0x268: case 0x269: case 0x26A: case 0x26B: case 0x26C: case 0x26D: case 0x26E: case 0x26F: + mtrr_fix4k_msr[ECX - 0x268] = EAX | ((uint64_t)EDX << 32); + break; + case 0x2FF: + mtrr_deftype_msr = EAX | ((uint64_t)EDX << 32); + break; + } break; - + +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)) case CPU_K5: case CPU_5K86: case CPU_K6: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; +#endif + +#ifdef USE_NEW_DYNAREC case CPU_K6_2: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~1ULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + + case CPU_K6_2C: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0xfULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + case CPU_K6_3: + switch (ECX) + { + case 0x0e: + msr.tr12 = EAX & 0x228; + break; + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + case 0x83: + ecx83_msr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0x1fULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; + case 0xC0000081: + star = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000089: + amd_l2aar = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); + break; + } + break; + case CPU_K6_2P: case CPU_K6_3P: switch (ECX) @@ -2488,14 +3167,40 @@ void cpu_WRMSR() case 0x83: ecx83_msr = EAX | ((uint64_t)EDX << 32); break; + case 0xC0000080: + temp = EAX | ((uint64_t)EDX << 32); + if (temp & ~0x1fULL) + x86gpf(NULL, 0); + else + amd_efer = temp; + break; case 0xC0000081: star = EAX | ((uint64_t)EDX << 32); break; - case 0xC0000084: - sfmask = EAX | ((uint64_t)EDX << 32); + case 0xC0000082: + amd_whcr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000085: + amd_uwccr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000086: + amd_epmr = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000087: + amd_psor = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000088: + amd_pfir = EAX | ((uint64_t)EDX << 32); + break; + case 0xC0000089: + amd_l2aar = EAX | ((uint64_t)EDX << 32); + break; + default: + x86gpf(NULL, 0); break; } break; +#endif case CPU_PENTIUM: case CPU_PENTIUMMMX: @@ -2506,6 +3211,7 @@ void cpu_WRMSR() break; } break; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) case CPU_Cx6x86: case CPU_Cx6x86L: case CPU_CxGX1: @@ -2517,10 +3223,12 @@ void cpu_WRMSR() break; } break; +#endif #ifdef DEV_BRANCH #ifdef USE_I686 case CPU_PENTIUMPRO: + case CPU_PENTIUM2: case CPU_PENTIUM2D: switch (ECX) { @@ -2606,6 +3314,7 @@ void cpu_WRMSR() break; default: i686_invalid_wrmsr: + // pclog("WRMSR: Invalid MSR: %08X\n", ECX); x86gpf(NULL, 0); break; } @@ -2649,6 +3358,7 @@ static void cpu_write(uint16_t addr, uint8_t val, void *priv) if ((ccr3 & 0xf0) == 0x10) { ccr4 = val; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)) if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_Cx6x86) { if (val & 0x80) @@ -2656,6 +3366,7 @@ static void cpu_write(uint16_t addr, uint8_t val, void *priv) else CPUID = 0; } +#endif } break; case 0xe9: /*CCR5*/ diff --git a/src/cpu/cpu.h b/src/cpu_common/cpu.h similarity index 77% rename from src/cpu/cpu.h rename to src/cpu_common/cpu.h index 62557bbd5..3672486f5 100644 --- a/src/cpu/cpu.h +++ b/src/cpu_common/cpu.h @@ -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 diff --git a/src/cpu_new/cpu_table.c b/src/cpu_common/cpu_table - Cópia.c similarity index 96% rename from src/cpu_new/cpu_table.c rename to src/cpu_common/cpu_table - Cópia.c index b6795074c..2c5676023 100644 --- a/src/cpu_new/cpu_table.c +++ b/src/cpu_common/cpu_table - Cópia.c @@ -45,9 +45,9 @@ #include #include #include -#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 diff --git a/src/cpu_common/cpu_table.c b/src/cpu_common/cpu_table.c new file mode 100644 index 000000000..f8422126b --- /dev/null +++ b/src/cpu_common/cpu_table.c @@ -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, + * leilei, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 leilei. + * Copyright 2016-2019 Miran Grca. + * Copyright 2017-2019 Fred N. van Kempen. + */ +#include +#include +#include +#include +#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} +}; \ No newline at end of file diff --git a/src/cpu_new/x86.h b/src/cpu_common/x86.h similarity index 100% rename from src/cpu_new/x86.h rename to src/cpu_common/x86.h diff --git a/src/cpu_new/x86_ops.h b/src/cpu_common/x86_ops.h similarity index 96% rename from src/cpu_new/x86_ops.h rename to src/cpu_common/x86_ops.h index 0de3b3252..34d1bcb24 100644 --- a/src/cpu_new/x86_ops.h +++ b/src/cpu_common/x86_ops.h @@ -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 diff --git a/src/cpu_new/x86_ops_3dnow.h b/src/cpu_common/x86_ops_3dnow.h similarity index 100% rename from src/cpu_new/x86_ops_3dnow.h rename to src/cpu_common/x86_ops_3dnow.h diff --git a/src/cpu/x86_ops_amd.h b/src/cpu_common/x86_ops_amd.h similarity index 100% rename from src/cpu/x86_ops_amd.h rename to src/cpu_common/x86_ops_amd.h diff --git a/src/cpu_new/x86_ops_arith.h b/src/cpu_common/x86_ops_arith.h similarity index 100% rename from src/cpu_new/x86_ops_arith.h rename to src/cpu_common/x86_ops_arith.h diff --git a/src/cpu_new/x86_ops_atomic.h b/src/cpu_common/x86_ops_atomic.h similarity index 100% rename from src/cpu_new/x86_ops_atomic.h rename to src/cpu_common/x86_ops_atomic.h diff --git a/src/cpu/x86_ops_bcd.h b/src/cpu_common/x86_ops_bcd.h similarity index 100% rename from src/cpu/x86_ops_bcd.h rename to src/cpu_common/x86_ops_bcd.h diff --git a/src/cpu_new/x86_ops_bit.h b/src/cpu_common/x86_ops_bit.h similarity index 100% rename from src/cpu_new/x86_ops_bit.h rename to src/cpu_common/x86_ops_bit.h diff --git a/src/cpu/x86_ops_bitscan.h b/src/cpu_common/x86_ops_bitscan.h similarity index 100% rename from src/cpu/x86_ops_bitscan.h rename to src/cpu_common/x86_ops_bitscan.h diff --git a/src/cpu/x86_ops_flag.h b/src/cpu_common/x86_ops_flag.h similarity index 98% rename from src/cpu/x86_ops_flag.h rename to src/cpu_common/x86_ops_flag.h index 8441b4987..099f2e35f 100644 --- a/src/cpu/x86_ops_flag.h +++ b/src/cpu_common/x86_ops_flag.h @@ -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 diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu_common/x86_ops_fpu.h similarity index 100% rename from src/cpu/x86_ops_fpu.h rename to src/cpu_common/x86_ops_fpu.h diff --git a/src/cpu_new/x86_ops_i686.h b/src/cpu_common/x86_ops_i686.h similarity index 98% rename from src/cpu_new/x86_ops_i686.h rename to src/cpu_common/x86_ops_i686.h index b4c1ed7ff..2b34e0822 100644 --- a/src/cpu_new/x86_ops_i686.h +++ b/src/cpu_common/x86_ops_i686.h @@ -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, - * 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; diff --git a/src/cpu/x86_ops_inc_dec.h b/src/cpu_common/x86_ops_inc_dec.h similarity index 100% rename from src/cpu/x86_ops_inc_dec.h rename to src/cpu_common/x86_ops_inc_dec.h diff --git a/src/cpu/x86_ops_int.h b/src/cpu_common/x86_ops_int.h similarity index 100% rename from src/cpu/x86_ops_int.h rename to src/cpu_common/x86_ops_int.h diff --git a/src/cpu/x86_ops_io.h b/src/cpu_common/x86_ops_io.h similarity index 100% rename from src/cpu/x86_ops_io.h rename to src/cpu_common/x86_ops_io.h diff --git a/src/cpu_new/x86_ops_jump.h b/src/cpu_common/x86_ops_jump.h similarity index 100% rename from src/cpu_new/x86_ops_jump.h rename to src/cpu_common/x86_ops_jump.h diff --git a/src/cpu/x86_ops_misc.h b/src/cpu_common/x86_ops_misc.h similarity index 99% rename from src/cpu/x86_ops_misc.h rename to src/cpu_common/x86_ops_misc.h index 08abe6790..91118211b 100644 --- a/src/cpu/x86_ops_misc.h +++ b/src/cpu_common/x86_ops_misc.h @@ -615,7 +615,8 @@ static int opHLT(uint32_t fetchdat) if (!((cpu_state.flags & I_FLAG) && pic_intpending)) { CLOCK_CYCLES_ALWAYS(100); - cpu_state.pc--; + if (!((cpu_state.flags & I_FLAG) && pic_intpending)) + cpu_state.pc--; } else CLOCK_CYCLES(5); diff --git a/src/cpu_new/x86_ops_mmx.h b/src/cpu_common/x86_ops_mmx.h similarity index 100% rename from src/cpu_new/x86_ops_mmx.h rename to src/cpu_common/x86_ops_mmx.h diff --git a/src/cpu_new/x86_ops_mmx_arith.h b/src/cpu_common/x86_ops_mmx_arith.h similarity index 100% rename from src/cpu_new/x86_ops_mmx_arith.h rename to src/cpu_common/x86_ops_mmx_arith.h diff --git a/src/cpu/x86_ops_mmx_cmp.h b/src/cpu_common/x86_ops_mmx_cmp.h similarity index 100% rename from src/cpu/x86_ops_mmx_cmp.h rename to src/cpu_common/x86_ops_mmx_cmp.h diff --git a/src/cpu/x86_ops_mmx_logic.h b/src/cpu_common/x86_ops_mmx_logic.h similarity index 100% rename from src/cpu/x86_ops_mmx_logic.h rename to src/cpu_common/x86_ops_mmx_logic.h diff --git a/src/cpu_new/x86_ops_mmx_mov.h b/src/cpu_common/x86_ops_mmx_mov.h similarity index 100% rename from src/cpu_new/x86_ops_mmx_mov.h rename to src/cpu_common/x86_ops_mmx_mov.h diff --git a/src/cpu_new/x86_ops_mmx_pack.h b/src/cpu_common/x86_ops_mmx_pack.h similarity index 100% rename from src/cpu_new/x86_ops_mmx_pack.h rename to src/cpu_common/x86_ops_mmx_pack.h diff --git a/src/cpu_new/x86_ops_mmx_shift.h b/src/cpu_common/x86_ops_mmx_shift.h similarity index 100% rename from src/cpu_new/x86_ops_mmx_shift.h rename to src/cpu_common/x86_ops_mmx_shift.h diff --git a/src/cpu/x86_ops_mov.h b/src/cpu_common/x86_ops_mov.h similarity index 99% rename from src/cpu/x86_ops_mov.h rename to src/cpu_common/x86_ops_mov.h index cf9bb82c0..dd49465bc 100644 --- a/src/cpu/x86_ops_mov.h +++ b/src/cpu_common/x86_ops_mov.h @@ -688,7 +688,7 @@ static int opMOV_r_l_a32(uint32_t fetchdat) return 0; } -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) #define opCMOV(condition) \ static int opCMOV ## condition ## _w_a16(uint32_t fetchdat) \ { \ diff --git a/src/cpu_new/x86_ops_mov_ctrl.h b/src/cpu_common/x86_ops_mov_ctrl.h similarity index 100% rename from src/cpu_new/x86_ops_mov_ctrl.h rename to src/cpu_common/x86_ops_mov_ctrl.h diff --git a/src/cpu/x86_ops_mov_seg.h b/src/cpu_common/x86_ops_mov_seg.h similarity index 100% rename from src/cpu/x86_ops_mov_seg.h rename to src/cpu_common/x86_ops_mov_seg.h diff --git a/src/cpu/x86_ops_movx.h b/src/cpu_common/x86_ops_movx.h similarity index 100% rename from src/cpu/x86_ops_movx.h rename to src/cpu_common/x86_ops_movx.h diff --git a/src/cpu/x86_ops_msr.h b/src/cpu_common/x86_ops_msr.h similarity index 100% rename from src/cpu/x86_ops_msr.h rename to src/cpu_common/x86_ops_msr.h diff --git a/src/cpu/x86_ops_mul.h b/src/cpu_common/x86_ops_mul.h similarity index 100% rename from src/cpu/x86_ops_mul.h rename to src/cpu_common/x86_ops_mul.h diff --git a/src/cpu_new/x86_ops_pmode.h b/src/cpu_common/x86_ops_pmode.h similarity index 100% rename from src/cpu_new/x86_ops_pmode.h rename to src/cpu_common/x86_ops_pmode.h diff --git a/src/cpu/x86_ops_prefix.h b/src/cpu_common/x86_ops_prefix.h similarity index 100% rename from src/cpu/x86_ops_prefix.h rename to src/cpu_common/x86_ops_prefix.h diff --git a/src/cpu/x86_ops_rep.h b/src/cpu_common/x86_ops_rep.h similarity index 100% rename from src/cpu/x86_ops_rep.h rename to src/cpu_common/x86_ops_rep.h diff --git a/src/cpu/x86_ops_ret.h b/src/cpu_common/x86_ops_ret.h similarity index 96% rename from src/cpu/x86_ops_ret.h rename to src/cpu_common/x86_ops_ret.h index 75419e6d8..1ebe67b9c 100644 --- a/src/cpu/x86_ops_ret.h +++ b/src/cpu_common/x86_ops_ret.h @@ -1,10 +1,16 @@ +#ifdef USE_NEW_DYNAREC +#define CPU_SET_OXPC +#else +#define CPU_SET_OXPC oxpc = cpu_state.pc; +#endif + #define RETF_a16(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ { \ pmoderetf(0, stack_offset); \ return 1; \ } \ - oxpc = cpu_state.pc; \ + CPU_SET_OXPC \ if (stack32) \ { \ cpu_state.pc = readmemw(ss, ESP); \ @@ -15,18 +21,18 @@ cpu_state.pc = readmemw(ss, SP); \ loadcs(readmemw(ss, SP + 2)); \ } \ - if (cpu_state.abrt) return 1; \ + if (cpu_state.abrt) return 1; \ if (stack32) ESP += 4 + stack_offset; \ else SP += 4 + stack_offset; \ cycles -= timing_retf_rm; #define RETF_a32(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ + if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ { \ pmoderetf(1, stack_offset); \ return 1; \ } \ - oxpc = cpu_state.pc; \ + CPU_SET_OXPC \ if (stack32) \ { \ cpu_state.pc = readmeml(ss, ESP); \ @@ -108,7 +114,7 @@ static int opIRET_286(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; + CPU_SET_OXPC if (stack32) { cpu_state.pc = readmemw(ss, ESP); @@ -184,7 +190,7 @@ static int opIRET(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; + CPU_SET_OXPC if (stack32) { cpu_state.pc = readmemw(ss, ESP); @@ -230,7 +236,7 @@ static int opIRETD(uint32_t fetchdat) else { uint16_t new_cs; - oxpc = cpu_state.pc; + CPU_SET_OXPC if (stack32) { cpu_state.pc = readmeml(ss, ESP); diff --git a/src/cpu/x86_ops_set.h b/src/cpu_common/x86_ops_set.h similarity index 100% rename from src/cpu/x86_ops_set.h rename to src/cpu_common/x86_ops_set.h diff --git a/src/cpu_new/x86_ops_stack.h b/src/cpu_common/x86_ops_stack.h similarity index 100% rename from src/cpu_new/x86_ops_stack.h rename to src/cpu_common/x86_ops_stack.h diff --git a/src/cpu_new/x86_ops_string.h b/src/cpu_common/x86_ops_string.h similarity index 100% rename from src/cpu_new/x86_ops_string.h rename to src/cpu_common/x86_ops_string.h diff --git a/src/cpu_new/x86_ops_xchg.h b/src/cpu_common/x86_ops_xchg.h similarity index 100% rename from src/cpu_new/x86_ops_xchg.h rename to src/cpu_common/x86_ops_xchg.h diff --git a/src/cpu/x86seg.h b/src/cpu_common/x86seg.h similarity index 100% rename from src/cpu/x86seg.h rename to src/cpu_common/x86seg.h diff --git a/src/cpu_new/x87.c b/src/cpu_common/x87.c similarity index 75% rename from src/cpu_new/x87.c rename to src/cpu_common/x87.c index 367948656..8a5363cd8 100644 --- a/src/cpu_new/x87.c +++ b/src/cpu_common/x87.c @@ -6,10 +6,10 @@ #define fplog 0 #include #define HAVE_STDARG_H -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" -#include "../pic.h" +#include "mem.h" +#include "pic.h" #include "x86.h" #include "x86_flags.h" #include "x86_ops.h" @@ -21,12 +21,12 @@ int fpu_do_log = ENABLE_FPU_LOG; -static void +void fpu_log(const char *fmt, ...) { va_list ap; - if (fpu_log) { + if (fpu_do_log) { va_start(ap, fmt); pclog_ex(fmt, ap); va_end(ap); @@ -37,6 +37,7 @@ fpu_log(const char *fmt, ...) #endif +#ifdef USE_NEW_DYNAREC #define X87_TAG_VALID 0 #define X87_TAG_ZERO 1 #define X87_TAG_INVALID 2 @@ -78,6 +79,35 @@ void x87_settag(uint16_t new_tag) cpu_state.tag[c] = TAG_VALID; } } +#else +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; +} +#endif #ifdef ENABLE_808X_LOG diff --git a/src/cpu_new/x87.h b/src/cpu_common/x87.h similarity index 62% rename from src/cpu_new/x87.h rename to src/cpu_common/x87.h index 2d61c14ae..be30c280c 100644 --- a/src/cpu_new/x87.h +++ b/src/cpu_common/x87.h @@ -8,22 +8,37 @@ uint16_t x87_pc_seg,x87_op_seg; static inline void x87_set_mmx() { +#ifdef USE_NEW_DYNAREC cpu_state.TOP = 0; *(uint64_t *)cpu_state.tag = 0x0101010101010101ull; cpu_state.ismmx = 1; +#else + uint64_t *p; + cpu_state.TOP = 0; + p = (uint64_t *)cpu_state.tag; + *p = 0; + cpu_state.ismmx = 1; +#endif } static inline void x87_emms() { +#ifdef USE_NEW_DYNAREC *(uint64_t *)cpu_state.tag = 0; cpu_state.ismmx = 0; +#else + uint64_t *p; + p = (uint64_t *)cpu_state.tag; + *p = 0; + cpu_state.ismmx = 0; +#endif } + uint16_t x87_gettag(); void x87_settag(uint16_t new_tag); -void x87_dumpregs(); -void x87_reset(); +#ifdef USE_NEW_DYNAREC #define TAG_EMPTY 0 #define TAG_VALID (1 << 0) /*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ @@ -35,3 +50,9 @@ void x87_reset(); #define X87_ROUNDING_CHOP 3 void codegen_set_rounding_mode(int mode); +#else +#define TAG_EMPTY 0 +#define TAG_VALID (1 << 0) +/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ +#define TAG_UINT64 (1 << 2) +#endif diff --git a/src/cpu/x87_ops.h b/src/cpu_common/x87_ops.h similarity index 97% rename from src/cpu/x87_ops.h rename to src/cpu_common/x87_ops.h index bf54afa40..239b449f2 100644 --- a/src/cpu/x87_ops.h +++ b/src/cpu_common/x87_ops.h @@ -25,6 +25,7 @@ #ifdef _MSC_VER # include #endif +// #include "x87_timings.h" #ifdef ENABLE_FPU_LOG extern void fpu_log(const char *fmt, ...); @@ -38,11 +39,6 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ #define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)] -#define C0 (1<<8) -#define C1 (1<<9) -#define C2 (1<<10) -#define C3 (1<<14) - #define STATUS_ZERODIVIDE 4 #ifdef FPU_8087 @@ -92,12 +88,18 @@ static __inline void x87_checkexceptions() static __inline void x87_push(double i) { +#ifdef USE_NEW_DYNAREC + cpu_state.TOP--; + cpu_state.ST[cpu_state.TOP&7] = i; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#else cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.ST[cpu_state.TOP] = i; cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; +#endif } -static inline void x87_push_u64(uint64_t i) +static __inline void x87_push_u64(uint64_t i) { union { @@ -107,26 +109,62 @@ static inline void x87_push_u64(uint64_t i) td.ll = i; +#ifdef USE_NEW_DYNAREC + cpu_state.TOP--; + cpu_state.ST[cpu_state.TOP&7] = td.d; + cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#else cpu_state.TOP=(cpu_state.TOP-1)&7; cpu_state.ST[cpu_state.TOP] = td.d; cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; +#endif } static __inline double x87_pop() { +#ifdef USE_NEW_DYNAREC + double t = cpu_state.ST[cpu_state.TOP&7]; + cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; + cpu_state.TOP++; + return t; +#else double t = cpu_state.ST[cpu_state.TOP]; cpu_state.tag[cpu_state.TOP&7] = 3; cpu_state.TOP=(cpu_state.TOP+1)&7; return t; +#endif } +static int old_round = FE_TONEAREST; + +static __inline void x87_round_save(void) +{ + old_round = fegetround(); +} + +static __inline void x87_round_set(void) +{ + old_round = fegetround(); + + fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); +} + +static __inline void x87_round_restore(void) +{ + fesetround(old_round); +} + +#ifdef PCEM_CODE static __inline int64_t x87_fround(double b) { +#ifdef PCEM_CODE int64_t a, c; +#endif - switch ((cpu_state.npxc>>10)&3) + switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ +#ifdef PCEM_CODE a = (int64_t)floor(b); c = (int64_t)floor(b + 1.0); if ((b - a) < (c - b)) @@ -135,16 +173,35 @@ static __inline int64_t x87_fround(double b) return c; else return (a & 1) ? c : a; +#else + return (int64_t)round(b); +#endif case 1: /*Down*/ return (int64_t)floor(b); case 2: /*Up*/ return (int64_t)ceil(b); case 3: /*Chop*/ +#ifdef PCEM_CODE return (int64_t)b; - default: - return (int64_t)0; +#else + return (int64_t)trunc(b); +#endif } + + return 0; } +#else +static __inline int64_t x87_fround(double b) +{ + int64_t ret; + + x87_round_set(); + ret = (int64_t) rint(b); + x87_round_restore(); + + return ret; +} +#endif #define BIAS80 16383 #define BIAS64 1023 @@ -155,6 +212,7 @@ static __inline double x87_ld80() int64_t exp64final; int64_t mant64; int64_t sign; + struct { int16_t begin; union @@ -163,6 +221,7 @@ static __inline double x87_ld80() uint64_t ll; } eind; } test; + test.eind.ll = readmeml(easeg,cpu_state.eaaddr); test.eind.ll |= (uint64_t)readmeml(easeg,cpu_state.eaaddr+4)<<32; test.begin = readmemw(easeg,cpu_state.eaaddr+8); @@ -251,6 +310,17 @@ static __inline void x87_ld_frstor(int reg) cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); +#ifdef USE_NEW_DYNAREC + if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) + { + cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; + } + else + { + cpu_state.tag[reg] &= ~TAG_UINT64; + cpu_state.ST[reg] = x87_ld80(); + } +#else if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2) { cpu_state.tag[reg] = TAG_UINT64; @@ -258,6 +328,7 @@ static __inline void x87_ld_frstor(int reg) } else cpu_state.ST[reg] = x87_ld80(); +#endif } static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) @@ -338,7 +409,7 @@ static __inline uint16_t x87_compare(double a, double b) #endif } -static inline uint16_t x87_ucompare(double a, double b) +static __inline uint16_t x87_ucompare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__ uint32_t result; @@ -412,6 +483,55 @@ typedef union } while (0) #endif +// #ifdef USE_NEW_DYNAREC +#if 1 +#define FP_TAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; +#define FP_LSTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; +#define FP_LSQ() cpu_state.MM[cpu_state.TOP&7].q = temp64; +#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP&7].q; +#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; +#ifdef USE_NEW_DYNAREC +#define FP_NNPXC() codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); +#else +#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); +#endif +#define FP_TOP(x) (x & 7) +#define FP_DTAG 0ULL +#define FP_CTAG 0x0101010101010101ull +#define FP_EMPTY TAG_EMPTY +#ifdef USE_NEW_DYNAREC +#define FP_RNPXC() codegen_set_rounding_mode(X87_ROUNDING_NEAREST); +#else +#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); +#endif +#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#define FP_DECTOP() cpu_state.TOP--; +#define FP_INCTOP() cpu_state.TOP++; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) +#define FP_686 +#endif +#else +#define FP_TAG() cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; +#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; +#define FP_LSTAG() cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; +#define FP_LSQ() cpu_state.MM[cpu_state.TOP].q = temp64; +#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP].q; +#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; +#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); +#define FP_TOP(x) (x) +#define FP_DTAG 0x0303030303030303ll +#define FP_CTAG 0ULL +#define FP_EMPTY 3 +#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); +#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = 1; +#define FP_DECTOP() cpu_state.TOP = (cpu_state.TOP - 1) & 7 +#define FP_INCTOP() cpu_state.TOP = (cpu_state.TOP + 1) & 7 +#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#define FP_686 +#endif +#endif + #include "x87_ops_arith.h" #include "x87_ops_misc.h" #include "x87_ops_loadstore.h" @@ -1050,7 +1170,7 @@ const OpFn OP_TABLE(fpu_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_da_a16)[256] = { opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, @@ -1283,7 +1403,7 @@ const OpFn OP_TABLE(fpu_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_db_a16)[256] = { opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, @@ -1856,7 +1976,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_df_a16)[256] = { opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, diff --git a/src/cpu_new/x87_ops_arith.h b/src/cpu_common/x87_ops_arith.h similarity index 83% rename from src/cpu_new/x87_ops_arith.h rename to src/cpu_common/x87_ops_arith.h index 26cab3ca6..e90761ca1 100644 --- a/src/cpu_new/x87_ops_arith.h +++ b/src/cpu_common/x87_ops_arith.h @@ -4,14 +4,12 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ - if ((cpu_state.npxc >> 10) & 3) \ - fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \ + x87_round_set(); \ ST(0) += use_var; \ - if ((cpu_state.npxc >> 10) & 3) \ - fesetround(FE_TONEAREST); \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -20,7 +18,7 @@ static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ @@ -32,7 +30,7 @@ static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ cpu_state.npxs &= ~(C0|C2|C3); \ cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \ @@ -45,10 +43,12 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ + x87_round_set(); \ x87_div(ST(0), ST(0), use_var); \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -57,10 +57,12 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ + x87_round_set(); \ x87_div(ST(0), use_var, ST(0)); \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -69,10 +71,12 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ + x87_round_set(); \ ST(0) *= use_var; \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -81,10 +85,12 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ + x87_round_set(); \ ST(0) -= use_var; \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -93,10 +99,12 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ optype t; \ FP_ENTER(); \ fetch_ea_ ## a_size(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ + SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ + x87_round_set(); \ ST(0) = use_var - ST(0); \ - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \ + x87_round_restore(); \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } @@ -121,12 +129,14 @@ opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t) #endif + + static int opFADD(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) + ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -135,7 +145,7 @@ static int opFADDr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -144,7 +154,7 @@ static int opFADDP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -174,10 +184,13 @@ static int opFCOMP(uint32_t fetchdat) static int opFCOMPP(uint32_t fetchdat) { + uint64_t *p, *q; FP_ENTER(); cpu_state.pc++; cpu_state.npxs &= ~(C0|C2|C3); - if (*(uint64_t *)&ST(0) == ((uint64_t)1 << 63) && *(uint64_t *)&ST(1) == 0) + p = (uint64_t *)&ST(0); + q = (uint64_t *)&ST(1); + if ((*p == ((uint64_t)1 << 63) && *q == 0) && is386) cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/ else cpu_state.npxs |= x87_compare(ST(0), ST(1)); @@ -200,6 +213,7 @@ static int opFUCOMPP(uint32_t fetchdat) return 0; } +#ifdef FP_686 static int opFCOMI(uint32_t fetchdat) { FP_ENTER(); @@ -224,13 +238,14 @@ static int opFCOMIP(uint32_t fetchdat) return 0; } #endif +#endif static int opFDIV(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; x87_div(ST(0), ST(0), ST(fetchdat & 7)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(73); return 0; } @@ -239,7 +254,7 @@ static int opFDIVr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(73); return 0; } @@ -248,7 +263,7 @@ static int opFDIVP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(73); return 0; @@ -259,7 +274,7 @@ static int opFDIVR(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(0), ST(fetchdat&7), ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(73); return 0; } @@ -268,7 +283,7 @@ static int opFDIVRr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(73); return 0; } @@ -277,7 +292,7 @@ static int opFDIVRP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(73); return 0; @@ -288,7 +303,7 @@ static int opFMUL(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(16); return 0; } @@ -297,7 +312,7 @@ static int opFMULr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(16); return 0; } @@ -306,7 +321,7 @@ static int opFMULP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(16); return 0; @@ -317,7 +332,7 @@ static int opFSUB(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -326,7 +341,7 @@ static int opFSUBr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -335,7 +350,7 @@ static int opFSUBP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -346,7 +361,7 @@ static int opFSUBR(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -355,7 +370,7 @@ static int opFSUBRr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -364,7 +379,7 @@ static int opFSUBRP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -392,6 +407,7 @@ static int opFUCOMP(uint32_t fetchdat) return 0; } +#ifdef FP_686 static int opFUCOMI(uint32_t fetchdat) { FP_ENTER(); @@ -416,3 +432,4 @@ static int opFUCOMIP(uint32_t fetchdat) return 0; } #endif +#endif diff --git a/src/cpu/x87_ops_loadstore.h b/src/cpu_common/x87_ops_loadstore.h similarity index 97% rename from src/cpu/x87_ops_loadstore.h rename to src/cpu_common/x87_ops_loadstore.h index 3001e8ca8..b5ad491f9 100644 --- a/src/cpu/x87_ops_loadstore.h +++ b/src/cpu_common/x87_ops_loadstore.h @@ -101,8 +101,8 @@ static int opFILDiq_a16(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp64 = geteaq(); if (cpu_state.abrt) return 1; x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; + FP_LSQ(); + FP_LSTAG(); CLOCK_CYCLES(10); return 0; @@ -116,8 +116,8 @@ static int opFILDiq_a32(uint32_t fetchdat) SEG_CHECK_READ(cpu_state.ea_seg); temp64 = geteaq(); if (cpu_state.abrt) return 1; x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP].q = temp64; - cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; + FP_LSQ(); + FP_LSTAG(); CLOCK_CYCLES(10); return 0; @@ -186,7 +186,7 @@ static int FISTPiq_a16(uint32_t fetchdat) fetch_ea_16(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP].q; + FP_LSRETQ() else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; @@ -202,7 +202,7 @@ static int FISTPiq_a32(uint32_t fetchdat) fetch_ea_32(fetchdat); SEG_CHECK_WRITE(cpu_state.ea_seg); if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP].q; + FP_LSRETQ() else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; diff --git a/src/cpu_new/x87_ops_misc.h b/src/cpu_common/x87_ops_misc.h similarity index 88% rename from src/cpu_new/x87_ops_misc.h rename to src/cpu_common/x87_ops_misc.h index 6cccfd429..406c6c86d 100644 --- a/src/cpu_new/x87_ops_misc.h +++ b/src/cpu_common/x87_ops_misc.h @@ -40,6 +40,7 @@ static int opFCLEX(uint32_t fetchdat) static int opFINIT(uint32_t fetchdat) { + uint64_t *p; FP_ENTER(); cpu_state.pc++; #ifdef FPU_8087 @@ -47,13 +48,14 @@ static int opFINIT(uint32_t fetchdat) #else cpu_state.npxc = 0x37F; #endif - codegen_set_rounding_mode(X87_ROUNDING_NEAREST); + FP_RNPXC(); cpu_state.npxs = 0; - *(uint64_t *)cpu_state.tag = 0; + p = (uint64_t *)cpu_state.tag; + *p = FP_DTAG; cpu_state.TOP = 0; - cpu_state.ismmx = 0; + cpu_state.ismmx = 0; CLOCK_CYCLES(17); - CPU_BLOCK_END(); + CPU_BLOCK_END(); return 0; } @@ -62,7 +64,7 @@ static int opFFREE(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; CLOCK_CYCLES(3); return 0; } @@ -71,8 +73,7 @@ static int opFFREEP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - fpu_log("FFREE\n"); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(3); return 0; @@ -104,13 +105,14 @@ static int opFSTP(uint32_t fetchdat) static int FSTOR() { + uint64_t *p; FP_ENTER(); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -119,7 +121,7 @@ static int FSTOR() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -138,9 +140,10 @@ static int FSTOR() 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 && (*(uint64_t *)cpu_state.tag == 0x0101010101010101ull)) + !cpu_state.TOP && (*p == FP_CTAG)) cpu_state.ismmx = 1; CLOCK_CYCLES((cr0 & 1) ? 34 : 44); @@ -150,7 +153,7 @@ static int opFSTOR_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -159,7 +162,7 @@ static int opFSTOR_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -167,8 +170,10 @@ static int opFSTOR_a32(uint32_t fetchdat) static int FSAVE() { + uint64_t *p; + FP_ENTER(); - cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (FP_TOP(cpu_state.TOP) << 11); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { @@ -300,9 +305,10 @@ static int FSAVE() } cpu_state.npxc = 0x37F; - codegen_set_rounding_mode(X87_ROUNDING_NEAREST); + FP_RNPXC(); cpu_state.npxs = 0; - *(uint64_t *)cpu_state.tag = 0; + p = (uint64_t *)cpu_state.tag; + *p = FP_DTAG; cpu_state.TOP = 0; cpu_state.ismmx = 0; @@ -313,7 +319,7 @@ static int opFSAVE_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -322,7 +328,7 @@ static int opFSAVE_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -332,8 +338,8 @@ static int opFSTSW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -342,8 +348,8 @@ static int opFSTSW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11)); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -360,8 +366,8 @@ static int opFLD(uint32_t fetchdat) old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; x87_push(ST(fetchdat&7)); - cpu_state.tag[cpu_state.TOP&7] = old_tag; - cpu_state.MM[cpu_state.TOP&7].q = old_i64; + cpu_state.tag[FP_TOP(cpu_state.TOP)] = old_tag; + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = old_i64; CLOCK_CYCLES(4); return 0; } @@ -376,11 +382,11 @@ static int opFXCH(uint32_t fetchdat) td = ST(0); ST(0) = ST(fetchdat&7); ST(fetchdat&7) = td; - old_tag = cpu_state.tag[cpu_state.TOP&7]; - cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; + old_tag = cpu_state.tag[FP_TOP(cpu_state.TOP)]; + cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag; - old_i64 = cpu_state.MM[cpu_state.TOP&7].q; - cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; + old_i64 = cpu_state.MM[FP_TOP(cpu_state.TOP)].q; + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; CLOCK_CYCLES(4); @@ -392,7 +398,7 @@ static int opFCHS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = -ST(0); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(6); return 0; } @@ -402,7 +408,7 @@ static int opFABS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = fabs(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(3); return 0; } @@ -423,7 +429,7 @@ static int opFXAM(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; cpu_state.npxs &= ~(C0|C1|C2|C3); - if (cpu_state.tag[cpu_state.TOP&7] == TAG_EMPTY) cpu_state.npxs |= (C0|C3); + if (cpu_state.tag[cpu_state.TOP&7] == FP_EMPTY) cpu_state.npxs |= (C0|C3); else if (ST(0) == 0.0) cpu_state.npxs |= C3; else cpu_state.npxs |= C2; if (ST(0) < 0.0) cpu_state.npxs |= C1; @@ -490,7 +496,7 @@ static int opFLDZ(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_push(0.0); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_ZTAG(); CLOCK_CYCLES(4); return 0; } @@ -500,7 +506,7 @@ static int opF2XM1(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = pow(2.0, ST(0)) - 1.0; - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(200); return 0; } @@ -510,7 +516,7 @@ static int opFYL2X(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(1) = ST(1) * (log(ST(0)) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -521,7 +527,7 @@ static int opFYL2XP1(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -532,7 +538,7 @@ static int opFPTAN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = tan(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); x87_push(1.0); cpu_state.npxs &= ~C2; CLOCK_CYCLES(235); @@ -544,7 +550,7 @@ static int opFPATAN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(1) = atan2(ST(1), ST(0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -554,7 +560,7 @@ static int opFDECSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.TOP--; + FP_DECTOP(); CLOCK_CYCLES(4); return 0; } @@ -563,7 +569,7 @@ static int opFINCSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.TOP++; + FP_INCTOP(); CLOCK_CYCLES(4); return 0; } @@ -575,7 +581,7 @@ static int opFPREM(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -591,7 +597,7 @@ static int opFPREM1(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -606,7 +612,7 @@ static int opFSQRT(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = sqrt(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(83); return 0; } @@ -619,7 +625,7 @@ static int opFSINCOS(uint32_t fetchdat) cpu_state.pc++; td = ST(0); ST(0) = sin(td); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); x87_push(cos(td)); cpu_state.npxs &= ~C2; CLOCK_CYCLES(330); @@ -629,10 +635,18 @@ static int opFSINCOS(uint32_t fetchdat) static int opFRNDINT(uint32_t fetchdat) { + double rounded; FP_ENTER(); cpu_state.pc++; - ST(0) = (double)x87_fround(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + rounded = (double) x87_fround(ST(0)); +#ifndef PCEM_CODE + if (rounded > ST(0)) + cpu_state.npxs |= C1; + else + cpu_state.npxs &= ~C1; +#endif + ST(0) = rounded; + FP_TAG(); CLOCK_CYCLES(21); return 0; } @@ -644,7 +658,7 @@ static int opFSCALE(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); CLOCK_CYCLES(30); return 0; } @@ -655,7 +669,7 @@ static int opFSIN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = sin(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -666,7 +680,7 @@ static int opFCOS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = cos(ST(0)); - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; + FP_TAG(); cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -682,7 +696,7 @@ static int FLDENV() case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -690,7 +704,7 @@ static int FLDENV() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -728,7 +742,7 @@ static int opFLDCW_a16(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); CLOCK_CYCLES(4); return 0; } @@ -742,7 +756,7 @@ static int opFLDCW_a32(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); + FP_NNPXC(); CLOCK_CYCLES(4); return 0; } @@ -832,6 +846,7 @@ static int opFSTCW_a32(uint32_t fetchdat) #endif #ifndef FPU_8087 +#ifdef FP_686 #define opFCMOV(condition) \ static int opFCMOV ## condition(uint32_t fetchdat) \ { \ @@ -839,8 +854,8 @@ static int opFSTCW_a32(uint32_t fetchdat) cpu_state.pc++; \ if (cond_ ## condition) \ { \ - cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ - cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ + cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ ST(0) = ST(fetchdat & 7); \ } \ CLOCK_CYCLES(4); \ @@ -859,3 +874,4 @@ opFCMOV(NE) opFCMOV(NBE) opFCMOV(NU) #endif +#endif diff --git a/src/cpu_new/386.c b/src/cpu_new/386.c deleted file mode 100644 index 2b2268920..000000000 --- a/src/cpu_new/386.c +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#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" -#include "codegen.h" - - -#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() - - -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; - - -static __inline void -fetch_ea_32_long(uint32_t rmdat) -{ - uint8_t sib; - uint32_t addr; - - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - if (cpu_rm == 4) { - 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) { - 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) -{ - uint32_t addr; - - 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) { - 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; - - 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 (x86_was_reset) - break; - } - - 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; - 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 != 0xFF) { - 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(); - } -} diff --git a/src/cpu_new/386_common.h b/src/cpu_new/386_common.h deleted file mode 100644 index 3ac390f98..000000000 --- a/src/cpu_new/386_common.h +++ /dev/null @@ -1,328 +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. - * - * Common 386 CPU code. - * - * Version: @(#)386_common.h 1.0.1 2019/02/19 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ - -#ifndef _386_COMMON_H_ -#define _386_COMMON_H_ - -#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 - -int checkio(int port); - -#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(NULL,0); \ - return 1; \ - } \ - } - -#define SEG_CHECK_READ(seg) \ - do \ - { \ - if ((seg)->base == 0xffffffff) \ - { \ - x86gpf("Segment can't read", 0);\ - return 1; \ - } \ - } while (0) - -#define SEG_CHECK_WRITE(seg) \ - do \ - { \ - if ((seg)->base == 0xffffffff) \ - { \ - x86gpf("Segment can't write", 0);\ - return 1; \ - } \ - } while (0) - -#define CHECK_READ(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) \ - { \ - x86gpf("Limit check (READ)", 0); \ - return 1; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ - return 1; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 0); \ - (void) mmutranslatereal((chseg)->base + high, 0); \ - if (cpu_state.abrt) \ - return 1; \ - } - -#define CHECK_READ_REP(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \ - { \ - x86gpf("Limit check (READ)", 0); \ - break; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Read from seg not present", (chseg)->seg & 0xfffc); \ - break; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 0); \ - (void) mmutranslatereal((chseg)->base + high, 0); \ - if (cpu_state.abrt) \ - break; \ - } - -#define CHECK_WRITE_COMMON(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) \ - { \ - x86gpf("Limit check (WRITE)", 0); \ - return 1; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Write to seg not present", (chseg)->seg & 0xfffc); \ - return 1; \ - } - -#define CHECK_WRITE(chseg, low, high) \ - CHECK_WRITE_COMMON(chseg, low, high) \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 1); \ - (void) mmutranslatereal((chseg)->base + high, 1); \ - if (cpu_state.abrt) \ - return 1; \ - } - -#define CHECK_WRITE_REP(chseg, low, high) \ - if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \ - { \ - x86gpf("Limit check (WRITE REP)", 0); \ - break; \ - } \ - if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \ - { \ - if ((chseg) == &cpu_state.seg_ss) \ - x86ss(NULL,(chseg)->seg & 0xfffc); \ - else \ - x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \ - break; \ - } \ - if (cr0 >> 31) { \ - (void) mmutranslatereal((chseg)->base + low, 1); \ - (void) mmutranslatereal((chseg)->base + high, 1); \ - if (cpu_state.abrt) \ - break; \ - } - - -#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\ - { \ - x86_int(6); \ - return 1; \ - } - - - - -static inline uint8_t fastreadb(uint32_t a) -{ - uint8_t *t; - - if ((a >> 12) == pccache) - return *((uint8_t *)&pccache2[a]); - t = getpccache(a); - if (cpu_state.abrt) - return 0; - pccache = a >> 12; - pccache2 = t; - return *((uint8_t *)&pccache2[a]); -} - -static inline uint16_t fastreadw(uint32_t a) -{ - uint8_t *t; - uint16_t val; - if ((a&0xFFF)>0xFFE) - { - val = fastreadb(a); - val |= (fastreadb(a + 1) << 8); - return val; - } - if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]); - t = getpccache(a); - if (cpu_state.abrt) - return 0; - - pccache = a >> 12; - pccache2 = t; - return *((uint16_t *)&pccache2[a]); -} - -static inline uint32_t fastreadl(uint32_t a) -{ - uint8_t *t; - uint32_t val; - if ((a&0xFFF)<0xFFD) - { - if ((a>>12)!=pccache) - { - t = getpccache(a); - if (cpu_state.abrt) - return 0; - pccache2 = t; - pccache=a>>12; - } - return *((uint32_t *)&pccache2[a]); - } - val = fastreadw(a); - val |= (fastreadw(a + 2) << 16); - return val; -} - -static inline void *get_ram_ptr(uint32_t a) -{ - if ((a >> 12) == pccache) - return &pccache2[a]; - else - { - uint8_t *t = getpccache(a); - return &t[a]; - } -} - -static inline uint8_t getbyte() -{ - cpu_state.pc++; - return fastreadb(cs + (cpu_state.pc - 1)); -} - -static inline uint16_t getword() -{ - cpu_state.pc+=2; - return fastreadw(cs+(cpu_state.pc-2)); -} - -static inline uint32_t getlong() -{ - cpu_state.pc+=4; - return fastreadl(cs+(cpu_state.pc-4)); -} - -static inline uint64_t getquad() -{ - cpu_state.pc+=8; - return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32); -} - - - -static inline uint8_t geteab() -{ - if (cpu_mod == 3) - return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l; - if (eal_r) - return *(uint8_t *)eal_r; - return readmemb(easeg,cpu_state.eaaddr); -} - -static inline uint16_t geteaw() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - if (eal_r) - return *(uint16_t *)eal_r; - return readmemw(easeg,cpu_state.eaaddr); -} - -static inline uint32_t geteal() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].l; - if (eal_r) - return *eal_r; - return readmeml(easeg,cpu_state.eaaddr); -} - -static inline uint64_t geteaq() -{ - return readmemq(easeg,cpu_state.eaaddr); -} - -static inline uint8_t geteab_mem() -{ - if (eal_r) return *(uint8_t *)eal_r; - return readmemb(easeg,cpu_state.eaaddr); -} -static inline uint16_t geteaw_mem() -{ - if (eal_r) return *(uint16_t *)eal_r; - return readmemw(easeg,cpu_state.eaaddr); -} -static inline uint32_t geteal_mem() -{ - if (eal_r) return *eal_r; - return readmeml(easeg,cpu_state.eaaddr); -} - -static __inline int seteaq_cwc(void) -{ - CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - return 0; -} - -static __inline void seteaq(uint64_t v) -{ - if (seteaq_cwc()) - return; - writememql(easeg + cpu_state.eaaddr, v); -} - -#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); 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 - -#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); - -#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 diff --git a/src/cpu_new/386_dynarec_ops.c b/src/cpu_new/386_dynarec_ops.c deleted file mode 100644 index 343ab13c3..000000000 --- a/src/cpu_new/386_dynarec_ops.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include -#include -#include -#include -#ifndef INFINITY -# define INFINITY (__builtin_inff()) -#endif -#include "../86box.h" -#include "cpu.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 "../pic.h" -#include "codegen.h" - -#define CPU_BLOCK_END() cpu_block_end = 1 - -#include "386_common.h" - - -static inline void fetch_ea_32_long(uint32_t rmdat) -{ - eal_r = eal_w = NULL; - easeg = cpu_state.ea_seg->base; - 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 (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++; 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) -#define PREFETCH_PREFIX() -#define PREFETCH_FLUSH() - -#define OP_TABLE(name) dynarec_ops_ ## name -/*Temporary*/ -#define CLOCK_CYCLES(c) -#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) - -#include "386_ops.h" diff --git a/src/cpu_new/808x.c b/src/cpu_new/808x.c deleted file mode 100644 index 266c48c63..000000000 --- a/src/cpu_new/808x.c +++ /dev/null @@ -1,2886 +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. - * - * 808x CPU emulation, mostly ported from reenigne's XTCE, which - * is cycle-accurate. - * - * Version: @(#)808x.c 1.0.9 2019/02/13 - * - * Authors: Andrew Jenner, - * Miran Grca, - * - * Copyright 2015-2019 Andrew Jenner. - * Copyright 2016-2019 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_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" - -/* The opcode of the instruction currently being executed. */ -uint8_t opcode; - -/* The tables to speed up the setting of the Z, N, and P cpu_state.flags. */ -uint8_t znptable8[256]; -uint16_t znptable16[65536]; - -/* A 16-bit zero, needed because some speed-up arrays contain pointers to it. */ -uint16_t zero = 0; - -/* MOD and R/M stuff. */ -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; -uint32_t rmdat; - -/* XT CPU multiplier. */ -uint64_t xt_cpu_multi; - -/* Is the CPU 8088 or 8086. */ -int is8086 = 0; - -/* Variables for handling the non-maskable interrupts. */ -int nmi = 0, nmi_auto_clear = 0; - -/* Was the CPU ever reset? */ -int x86_was_reset = 0; - -/* Amount of instructions executed - used to calculate the % shown in the title bar. */ -int ins = 0; - -/* Is the TRAP flag on? */ -int trap = 0; - -/* The current effective address's segment. */ -uint32_t easeg; - - -/* The prefetch queue (4 bytes for 8088, 6 bytes for 8086). */ -static uint8_t pfq[6]; - -/* Variables to aid with the prefetch queue operation. */ -static int biu_cycles = 0, pfq_pos = 0; - -/* The IP equivalent of the current prefetch queue position. */ -static uint16_t pfq_ip; - -/* Pointer tables needed for segment overrides. */ -static uint32_t *opseg[4]; -static x86seg *_opseg[4]; - -static int noint = 0; -static int in_lock = 0; -static int cpu_alu_op, pfq_size; - -static uint16_t cpu_src = 0, cpu_dest = 0; -static uint16_t cpu_data = 0, last_addr = 0x0000; - -static uint32_t *ovr_seg = NULL; -static int prefetching = 1, completed = 1; -static int in_rep = 0, repeating = 0; -static int oldc, clear_lock = 0; -static int refresh = 0, takeint = 0; -static int cycdiff; - - -/* Various things needed for 8087. */ -#define OP_TABLE(name) ops_ ## name - -#define CPU_BLOCK_END() -#define SEG_CHECK_READ(seg) -#define SEG_CHECK_WRITE(seg) -#define CHECK_READ(a, b, c) -#define CHECK_WRITE(a, b, c) -#define UN_USED(x) (void)(x) -#define fetch_ea_16(val) -#define fetch_ea_32(val) -#define PREFETCH_RUN(a, b, c, d, e, f, g, h) - -#define CYCLES(val) \ - { \ - wait(val, 0); \ - } - -#define CLOCK_CYCLES(val) \ - { \ - wait(val, 0); \ - } - -typedef int (*OpFn)(uint32_t fetchdat); - - -static int tempc_fpu = 0; - - -#ifdef ENABLE_808X_LOG -void dumpregs(int); - -int x808x_do_log = ENABLE_808X_LOG; -int indump = 0; - - -static void -x808x_log(const char *fmt, ...) -{ - va_list ap; - - if (x808x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} - - -void -dumpregs(int force) -{ - int c; - char *seg_names[4] = { "ES", "CS", "SS", "DS" }; - - /* Only dump when needed, and only once.. */ - if (indump || (!force && !dump_on_exit)) - return; - - x808x_log("EIP=%08X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n", - cpu_state.pc, CS, DS, ES, SS, cpu_state.flags); - x808x_log("Old CS:EIP: %04X:%08X; %i ins\n", oldcs, cpu_state.oldpc, ins); - for (c = 0; c < 4; c++) { - x808x_log("%s : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - seg_names[c], _opseg[c]->base, _opseg[c]->limit, - _opseg[c]->access, _opseg[c]->limit_low, _opseg[c]->limit_high); - } - if (is386) { - x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - seg_fs, cpu_state.seg_fs.limit, cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high); - x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n", - gs, cpu_state.seg_gs.limit, cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high); - x808x_log("GDT : base=%06X limit=%04X\n", gdt.base, gdt.limit); - x808x_log("LDT : base=%06X limit=%04X\n", ldt.base, ldt.limit); - x808x_log("IDT : base=%06X limit=%04X\n", idt.base, idt.limit); - x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); - x808x_log("386 in %s mode: %i-bit data, %-i-bit stack\n", - (msw & 1) ? ((cpu_state.eflags & VM_FLAG) ? "V86" : "protected") : "real", - (use32) ? 32 : 16, (stack32) ? 32 : 16); - x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n", cr0, cr2, cr3, cr4); - x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n", - EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP); - } else { - x808x_log("808x/286 in %s mode\n", (msw & 1) ? "protected" : "real"); - x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n", - AX, BX, CX, DX, DI, SI, BP, SP); - } - x808x_log("Entries in readlookup : %i writelookup : %i\n", readlnum, writelnum); - x87_dumpregs(); - indump = 0; -} -#else -#define x808x_log(fmt, ...) -#endif - - -static void pfq_add(int c, int add); -static void set_pzs(int bits); - - -uint16_t -get_last_addr(void) -{ - return last_addr; -} - - -static int -irq_pending(void) -{ - uint8_t temp; - - if (takeint && !noint) - temp = 1; - else - temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint); - - takeint = (cpu_state.flags & I_FLAG) && (pic.pend &~ pic.mask); - - return temp; -} - - -static void -clock_start(void) -{ - cycdiff = cycles; -} - - -static void -clock_end(void) -{ - int diff = cycdiff - cycles; - - /* On 808x systems, clock speed is usually crystal frequency divided by an integer. */ - tsc += (uint64_t)diff * ((uint64_t)xt_cpu_multi >> 32ULL); /* Shift xt_cpu_multi by 32 bits to the right and then multiply. */ - if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) - timer_process(); -} - - -static void -fetch_and_bus(int c, int bus) -{ - if (refresh > 0) { - /* Finish the current fetch, if any. */ - cycles -= ((4 - (biu_cycles & 3)) & 3); - pfq_add((4 - (biu_cycles & 3)) & 3, 1); - /* Add 4 memory access cycles. */ - cycles -= 4; - pfq_add(4, 0); - - refresh--; - } - - pfq_add(c, !bus); - clock_end(); - clock_start(); -} - - -static void -wait(int c, int bus) -{ - cycles -= c; - - fetch_and_bus(c, bus); -} - - -/* This is for external subtraction of cycles. */ -void -sub_cycles(int c) -{ - cycles -= c; - - if (!is286) - fetch_and_bus(c, 1); -} - - -#undef readmemb -#undef readmemw -#undef readmeml -#undef readmemq - -/* Common read function. */ -static uint8_t -readmemb_common(uint32_t a) -{ - uint8_t ret; - - if (readlookup2 == NULL) - ret = readmembl(a); - else { - if (readlookup2[(a) >> 12] == ((uintptr_t) -1)) - ret = readmembl(a); - else - ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a)); - } - - return ret; -} - -/* Reads a byte from the memory and advances the BIU. */ -static uint8_t -readmemb(uint32_t a) -{ - uint8_t ret; - - wait(4, 1); - ret = readmemb_common(a); - - return ret; -} - - -/* Reads a byte from the memory but does not advance the BIU. */ -static uint8_t -readmembf(uint32_t a) -{ - uint8_t ret; - - a = cs + (a & 0xffff); - ret = readmemb_common(a); - - return ret; -} - - -/* Reads a word from the memory and advances the BIU. */ -static uint16_t -readmemw_common(uint32_t s, uint16_t a) -{ - uint16_t ret; - - ret = readmemb_common(s + a); - ret |= readmemb_common(s + ((a + 1) & 0xffff)) << 8; - - return ret; -} - - -static uint16_t -readmemw(uint32_t s, uint16_t a) -{ - uint16_t ret; - - if (is8086 && !(a & 1)) - wait(4, 1); - else - wait(8, 1); - ret = readmemw_common(s, a); - - return ret; -} - - -static uint16_t -readmemwf(uint16_t a) -{ - uint16_t ret; - - ret = readmemw_common(cs, a & 0xffff); - - return ret; -} - - -static uint16_t -readmem(uint32_t s) -{ - if (opcode & 1) - return readmemw(s, cpu_state.eaaddr); - else - return (uint16_t) readmemb(s + cpu_state.eaaddr); -} - - -static uint32_t -readmeml(uint32_t s, uint16_t a) -{ - uint32_t temp; - - temp = (uint32_t) (readmemw(s, a + 2)) << 16; - temp |= readmemw(s, a); - - return temp; -} - - -static uint64_t -readmemq(uint32_t s, uint16_t a) -{ - uint64_t temp; - - temp = (uint64_t) (readmeml(s, a + 4)) << 32; - temp |= readmeml(s, a); - - return temp; -} - - -static void -writememb_common(uint32_t a, uint8_t v) -{ - if (writelookup2 == NULL) - writemembl(a, v); - else { - if (writelookup2[(a) >> 12] == ((uintptr_t) -1)) - writemembl(a, v); - else - *(uint8_t *)(writelookup2[a >> 12] + a) = v; - } - - if ((a >= 0xf0000) && (a <= 0xfffff)) - last_addr = a & 0xffff; -} - - -/* Writes a byte to the memory and advances the BIU. */ -static void -writememb(uint32_t s, uint32_t a, uint8_t v) -{ - wait(4, 1); - writememb_common(s + a, v); -} - - -/* Writes a word to the memory and advances the BIU. */ -static void -writememw(uint32_t s, uint32_t a, uint16_t v) -{ - if (is8086 && !(a & 1)) - wait(4, 1); - else - wait(8, 1); - writememb_common(s + a, v & 0xff); - writememb_common(s + ((a + 1) & 0xffff), v >> 8); -} - - -static void -writemem(uint32_t s, uint16_t v) -{ - if (opcode & 1) - return writememw(s, cpu_state.eaaddr, v); - else - return writememb(s, cpu_state.eaaddr, (uint8_t) (v & 0xff)); -} - - -static void -writememl(uint32_t s, uint32_t a, uint32_t v) -{ - writememw(s, a, v & 0xffff); - writememw(s, a + 2, v >> 16); -} - - -static void -writememq(uint32_t s, uint32_t a, uint64_t v) -{ - writememl(s, a, v & 0xffffffff); - writememl(s, a + 4, v >> 32); -} - - -static void -pfq_write(void) -{ - uint16_t tempw; - - if (is8086 && (pfq_pos < (pfq_size - 1))) { - /* The 8086 fetches 2 bytes at a time, and only if there's at least 2 bytes - free in the queue. */ - tempw = readmemwf(pfq_ip); - *(uint16_t *) &(pfq[pfq_pos]) = tempw; - pfq_ip += 2; - pfq_pos += 2; - } else if (!is8086 && (pfq_pos < pfq_size)) { - /* The 8088 fetches 1 byte at a time, and only if there's at least 1 byte - free in the queue. */ - pfq[pfq_pos] = readmembf(pfq_ip); - pfq_ip++; - pfq_pos++; - } -} - - -static uint8_t -pfq_read(void) -{ - uint8_t temp, i; - - temp = pfq[0]; - for (i = 0; i < (pfq_size - 1); i++) - pfq[i] = pfq[i + 1]; - pfq_pos--; - cpu_state.pc = (cpu_state.pc + 1) & 0xffff; - return temp; -} - - -/* Fetches a byte from the prefetch queue, or from memory if the queue has - been drained. */ -static uint8_t -pfq_fetchb_common(void) -{ - uint8_t temp; - - if (pfq_pos == 0) { - /* Reset prefetch queue internal position. */ - pfq_ip = cpu_state.pc; - /* Fill the queue. */ - wait(4 - (biu_cycles & 3), 0); - } - - /* Fetch. */ - temp = pfq_read(); - return temp; -} - - -static uint8_t -pfq_fetchb(void) -{ - uint8_t ret; - - ret = pfq_fetchb_common(); - wait(1, 0); - return ret; -} - - -/* Fetches a word from the prefetch queue, or from memory if the queue has - been drained. */ -static uint16_t -pfq_fetchw(void) -{ - uint16_t temp; - - temp = pfq_fetchb_common(); - wait(1, 0); - temp |= (pfq_fetchb_common() << 8); - - return temp; -} - - -static uint16_t -pfq_fetch() -{ - if (opcode & 1) - return pfq_fetchw(); - else - return (uint16_t) pfq_fetchb(); -} - - -/* Adds bytes to the prefetch queue based on the instruction's cycle count. */ -static void -pfq_add(int c, int add) -{ - int d; - - if ((c <= 0) || (pfq_pos >= pfq_size)) - return; - - for (d = 0; d < c; d++) { - biu_cycles = (biu_cycles + 1) & 0x03; - if (prefetching && add && (biu_cycles == 0x00)) - pfq_write(); - } -} - - -/* Clear the prefetch queue - called on reset and on anything that affects either CS or IP. */ -static void -pfq_clear() -{ - pfq_pos = 0; - prefetching = 0; -} - - -static void -set_ip(uint16_t new_ip) { - pfq_ip = cpu_state.pc = new_ip; - prefetching = 1; -} - - -/* Memory refresh read - called by reads and writes on DMA channel 0. */ -void -refreshread(void) { - refresh++; -} - - -/* Preparation of the various arrays needed to speed up the MOD and R/M work. */ -static void -makemod1table(void) -{ - mod1add[0][0] = &BX; - mod1add[0][1] = &BX; - mod1add[0][2] = &BP; - mod1add[0][3] = &BP; - mod1add[0][4] = &SI; - mod1add[0][5] = &DI; - mod1add[0][6] = &BP; - mod1add[0][7] = &BX; - mod1add[1][0] = &SI; - mod1add[1][1] = &DI; - mod1add[1][2] = &SI; - mod1add[1][3] = &DI; - mod1add[1][4] = &zero; - mod1add[1][5] = &zero; - mod1add[1][6] = &zero; - mod1add[1][7] = &zero; - mod1seg[0] = &ds; - mod1seg[1] = &ds; - mod1seg[2] = &ss; - mod1seg[3] = &ss; - mod1seg[4] = &ds; - mod1seg[5] = &ds; - mod1seg[6] = &ss; - mod1seg[7] = &ds; - opseg[0] = &es; - opseg[1] = &cs; - opseg[2] = &ss; - opseg[3] = &ds; - _opseg[0] = &cpu_state.seg_es; - _opseg[1] = &cpu_state.seg_cs; - _opseg[2] = &cpu_state.seg_ss; - _opseg[3] = &cpu_state.seg_ds; -} - - -static uint16_t -sign_extend(uint8_t data) -{ - return data + (data < 0x80 ? 0 : 0xff00); -} - - -/* Fetches the effective address from the prefetch queue according to MOD and R/M. */ -static void -do_mod_rm(void) -{ - rmdat = pfq_fetchb(); - cpu_reg = (rmdat >> 3) & 7; - cpu_mod = (rmdat >> 6) & 3; - cpu_rm = rmdat & 7; - - if (cpu_mod == 3) - return; - - wait(1, 0); - if ((rmdat & 0xc7) == 0x06) { - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - easeg = ovr_seg ? *ovr_seg : ds; - wait(1, 0); - return; - } else switch (cpu_rm) { - case 0: - case 3: - wait(2, 0); - break; - case 1: - case 2: - wait(3, 0); - break; - } - cpu_state.eaaddr = (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]); - easeg = ovr_seg ? *ovr_seg : *mod1seg[cpu_rm]; - switch (rmdat & 0xc0) { - case 0x40: - wait(3, 0); - cpu_state.eaaddr += sign_extend(pfq_fetchb()); - break; - case 0x80: - wait(3, 0); - cpu_state.eaaddr += pfq_fetchw(); - break; - } - cpu_state.eaaddr &= 0xffff; - wait(2, 0); -} - - -#undef getr8 -#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) - -#undef setr8 -#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \ - else cpu_state.regs[r & 3].b.l = v; - - -/* Reads a byte from the effective address. */ -static uint8_t -geteab(void) -{ - if (cpu_mod == 3) - return (getr8(cpu_rm)); - - return readmemb(easeg + cpu_state.eaaddr); -} - - -/* Reads a word from the effective address. */ -static uint16_t -geteaw(void) -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - - return readmemw(easeg, cpu_state.eaaddr); -} - - -/* Neede for 8087 - memory only. */ -static uint32_t -geteal(void) -{ - if (cpu_mod == 3) { - fatal("808x register geteal()\n"); - return 0xffffffff; - } - - return readmeml(easeg, cpu_state.eaaddr); -} - - -/* Neede for 8087 - memory only. */ -static uint64_t -geteaq(void) -{ - if (cpu_mod == 3) { - fatal("808x register geteaq()\n"); - return 0xffffffff; - } - - return readmemq(easeg, cpu_state.eaaddr); -} - - -static void -read_ea(int memory_only, int bits) -{ - if (cpu_mod != 3) { - if (bits == 16) - cpu_data = readmemw(easeg, cpu_state.eaaddr); - else - cpu_data = readmemb(easeg + cpu_state.eaaddr); - return; - } - if (!memory_only) { - if (bits == 8) { - cpu_data = getr8(cpu_rm); - } else - cpu_data = cpu_state.regs[cpu_rm].w; - } -} - - -static void -read_ea2(int bits) -{ - cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - if (bits == 16) - cpu_data = readmemw(easeg, cpu_state.eaaddr); - else - cpu_data = readmemb(easeg + cpu_state.eaaddr); -} - - -/* Writes a byte to the effective address. */ -static void -seteab(uint8_t val) -{ - if (cpu_mod == 3) { - setr8(cpu_rm, val); - } else - writememb(easeg, cpu_state.eaaddr, val); -} - - -/* Writes a word to the effective address. */ -static void -seteaw(uint16_t val) -{ - if (cpu_mod == 3) - cpu_state.regs[cpu_rm].w = val; - else - writememw(easeg, cpu_state.eaaddr, val); -} - - -static void -seteal(uint32_t val) -{ - if (cpu_mod == 3) { - fatal("808x register seteal()\n"); - return; - } else - writememl(easeg, cpu_state.eaaddr, val); -} - - -static void -seteaq(uint64_t val) -{ - if (cpu_mod == 3) { - fatal("808x register seteaq()\n"); - return; - } else - writememq(easeg, cpu_state.eaaddr, val); -} - - -/* Leave out the 686 stuff as it's not needed and - complicates compiling. */ -#define FPU_8087 -#define tempc tempc_fpu -#include "x87.h" -#include "x87_ops.h" -#undef tempc -#undef FPU_8087 - - -/* Prepare the ZNP table needed to speed up the setting of the Z, N, and P cpu_state.flags. */ -static void -makeznptable(void) -{ - int c, d, e; - for (c = 0; c < 256; c++) { - d = 0; - for (e = 0; e < 8; e++) { - if (c & (1 << e)) - d++; - } - if (d & 1) - znptable8[c] = 0; - else - znptable8[c] = P_FLAG; -#ifdef ENABLE_808X_LOG - if (c == 0xb1) - x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]); -#endif - if (!c) - znptable8[c] |= Z_FLAG; - if (c & 0x80) - znptable8[c] |= N_FLAG; - } - - for (c = 0; c < 65536; c++) { - d = 0; - for (e = 0; e < 8; e++) { - if (c & (1 << e)) - d++; - } - if (d & 1) - znptable16[c] = 0; - else - znptable16[c] = P_FLAG; -#ifdef ENABLE_808X_LOG - if (c == 0xb1) - x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) - x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); -#endif - if (!c) - znptable16[c] |= Z_FLAG; - if (c & 0x8000) - znptable16[c] |= N_FLAG; - } -} - - -/* Common reset function. */ -static void -reset_common(int hard) -{ - biu_cycles = 0; - in_rep = 0; - in_lock = 0; - completed = 1; - repeating = 0; - clear_lock = 0; - refresh = 0; - - if (hard) { -#ifdef ENABLE_808X_LOG - x808x_log("x86 reset\n"); -#endif - ins = 0; - } - use32 = 0; - cpu_cur_status = 0; - stack32 = 0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw = 0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - if (isibmcpu) - cpu_cache_int_enabled = 1; - else - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - cpu_state.eflags = 0; - cgate32 = 0; - if (AT) { - loadcs(0xF000); - cpu_state.pc = 0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } else { - loadcs(0xFFFF); - cpu_state.pc = 0; - rammask = 0xfffff; - } - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - cpu_state.flags = 2; - trap = 0; - ovr_seg = NULL; - in_lock = 0; - - EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0; - - if (hard) { - makeznptable(); - resetreadlookup(); - makemod1table(); - resetmcr(); - pfq_clear(); - cpu_set_edx(); - mmu_perm = 4; - pfq_size = (is8086) ? 6 : 4; - } - x86seg_reset(); -#ifdef USE_DYNAREC - if (hard) - codegen_reset(); -#endif - if (!hard) - flushmmucache(); - x86_was_reset = 1; - cpu_alt_reset = 0; - - prefetching = 1; - takeint = 0; -} - - -/* Hard reset. */ -void -resetx86(void) -{ - reset_common(1); -} - - -/* Soft reset. */ -void -softresetx86(void) -{ - reset_common(0); -} - - -/* Pushes a word to the stack. */ -static void -push(uint16_t *val) -{ - SP -= 2; - cpu_state.eaaddr = (SP & 0xffff); - writememw(ss, cpu_state.eaaddr, *val); -} - - -/* Pops a word from the stack. */ -static uint16_t -pop(void) -{ - cpu_state.eaaddr = (SP & 0xffff); - SP += 2; - return readmemw(ss, cpu_state.eaaddr); -} - - -static void -access(int num, int bits) -{ - switch (num) { - case 0: case 61: case 63: case 64: - case 67: case 69: case 71: case 72: - default: - break; - case 1: case 6: case 7: case 8: - case 9: case 17: case 20: case 21: - case 24: case 28: case 47: case 48: - case 49: case 50: case 51: case 55: - case 56: case 62: case 66: case 68: - wait(1, 0); - break; - case 3: case 11: case 15: case 22: - case 23: case 25: case 26: case 35: - case 44: case 45: case 46: case 52: - case 53: case 54: - wait(2, 0); - break; - case 16: case 18: case 19: case 27: - case 32: case 37: case 42: - wait(3, 0); - break; - case 10: case 12: case 13: case 14: - case 29: case 30: case 33: case 34: - case 39: case 41: case 60: - wait(4, 0); - break; - case 4: case 70: - wait(5, 0); - break; - case 31: case 38: case 40: - wait(6, 0); - break; - case 5: - if (opcode == 0xcc) - wait(7, 0); - else - wait(4, 0); - break; - case 36: - wait(1, 0); - pfq_clear(); - wait (1, 0); - if (cpu_mod != 3) - wait(1, 0); - wait(3, 0); - break; - case 43: - wait(2, 0); - pfq_clear(); - wait(1, 0); - break; - case 57: - if (cpu_mod != 3) - wait(2, 0); - wait(4, 0); - break; - case 58: - if (cpu_mod != 3) - wait(1, 0); - wait(4, 0); - break; - case 59: - wait(2, 0); - pfq_clear(); - if (cpu_mod != 3) - wait(1, 0); - wait(3, 0); - break; - case 65: - wait(1, 0); - pfq_clear(); - wait(2, 0); - if (cpu_mod != 3) - wait(1, 0); - break; - } -} - - -/* Calls an interrupt. */ -static void -interrupt(uint16_t addr) -{ - uint16_t old_cs, old_ip; - uint16_t new_cs, new_ip; - uint16_t tempf; - - addr <<= 2; - cpu_state.eaaddr = addr; - old_cs = CS; - access(5, 16); - new_ip = readmemw(0, cpu_state.eaaddr); - wait(1, 0); - cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff; - access(6, 16); - new_cs = readmemw(0, cpu_state.eaaddr); - pfq_clear(); - access(39, 16); - tempf = cpu_state.flags & 0x0fd7; - push(&tempf); - cpu_state.flags &= ~(I_FLAG | T_FLAG); - access(40, 16); - push(&old_cs); - old_ip = cpu_state.pc; - loadcs(new_cs); - access(68, 16); - set_ip(new_ip); - access(41, 16); - push(&old_ip); -} - - -static void -check_interrupts(void) -{ - int temp; - - if (irq_pending()) { - if ((cpu_state.flags & T_FLAG) && !noint) { - interrupt(1); - return; - } - if (nmi && nmi_enable && nmi_mask) { - nmi_enable = 0; - interrupt(2); - return; - } - temp = picinterrupt(); - if (temp != -1) { - repeating = 0; - completed = 1; - ovr_seg = NULL; - in_lock = 0; - clear_lock = 0; - ovr_seg = NULL; - wait(9, 0); - interrupt((uint16_t) (temp & 0xffff)); - } - } -} - - -static int -rep_action(int bits) -{ - uint16_t t; - - if (in_rep == 0) - return 0; - wait(2, 0); - t = CX; - if (irq_pending() && (repeating != 0)) { - access(71, bits); - pfq_clear(); - set_ip(cpu_state.pc - 2); - t = 0; - } - if (t == 0) { - wait(1, 0); - completed = 1; - repeating = 0; - return 1; - } - --CX; - completed = 0; - wait(2, 0); - if (!repeating) - wait(2, 0); - return 0; -} - - -static uint16_t -jump(uint16_t delta) -{ - uint16_t old_ip; - access(67, 8); - pfq_clear(); - wait(5, 0); - old_ip = cpu_state.pc; - set_ip((cpu_state.pc + delta) & 0xffff); - return old_ip; -} - - -static void -jump_short(void) -{ - jump(sign_extend((uint8_t) cpu_data)); -} - - -static uint16_t -jump_near(void) -{ - return jump(pfq_fetchw()); -} - - -/* Performs a conditional jump. */ -static void -jcc(uint8_t opcode, int cond) -{ - /* int8_t offset; */ - - wait(1, 0); - cpu_data = pfq_fetchb(); - wait(1, 0); - if ((!cond) == (opcode & 0x01)) - jump_short(); -} - - -static void -set_cf(int cond) -{ - cpu_state.flags = (cpu_state.flags & ~C_FLAG) | (cond ? C_FLAG : 0); -} - - -static void -set_if(int cond) -{ - cpu_state.flags = (cpu_state.flags & ~I_FLAG) | (cond ? I_FLAG : 0); -} - - -static void -set_df(int cond) -{ - cpu_state.flags = (cpu_state.flags & ~D_FLAG) | (cond ? D_FLAG : 0); -} - - -static void -bitwise(int bits, uint16_t data) -{ - cpu_data = data; - cpu_state.flags &= ~(C_FLAG | A_FLAG | V_FLAG); - set_pzs(bits); -} - - -static void -test(int bits, uint16_t dest, uint16_t src) -{ - cpu_dest = dest; - cpu_src = src; - bitwise(bits, (cpu_dest & cpu_src)); -} - - -static void -set_of(int of) -{ - cpu_state.flags = (cpu_state.flags & ~0x800) | (of ? 0x800 : 0); -} - - -static int -top_bit(uint16_t w, int bits) -{ - if (bits == 16) - return ((w & 0x8000) != 0); - else - return ((w & 0x80) != 0); -} - - -static void -set_of_add(int bits) -{ - set_of(top_bit((cpu_data ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); -} - - -static void -set_of_sub(int bits) -{ - set_of(top_bit((cpu_dest ^ cpu_src) & (cpu_data ^ cpu_dest), bits)); -} - - -static void -set_af(int af) -{ - cpu_state.flags = (cpu_state.flags & ~0x10) | (af ? 0x10 : 0); -} - - -static void -do_af(void) -{ - set_af(((cpu_data ^ cpu_src ^ cpu_dest) & 0x10) != 0); -} - - -static void -set_apzs(int bits) -{ - set_pzs(bits); - do_af(); -} - - -static void -add(int bits) -{ - int size_mask = (1 << bits) - 1; - - cpu_data = cpu_dest + cpu_src; - set_apzs(bits); - set_of_add(bits); - - /* Anything - FF with carry on is basically anything + 0x100: value stays - unchanged but carry goes on. */ - if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) - cpu_state.flags |= C_FLAG; - else - set_cf((cpu_src & size_mask) > (cpu_data & size_mask)); -} - - -static void -sub(int bits) -{ - int size_mask = (1 << bits) - 1; - - cpu_data = cpu_dest - cpu_src; - set_apzs(bits); - set_of_sub(bits); - - /* Anything - FF with carry on is basically anything - 0x100: value stays - unchanged but carry goes on. */ - if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG)) - cpu_state.flags |= C_FLAG; - else - set_cf((cpu_src & size_mask) > (cpu_dest & size_mask)); -} - - -static void -alu_op(int bits) -{ - switch(cpu_alu_op) { - case 1: - bitwise(bits, (cpu_dest | cpu_src)); - break; - case 2: - if (cpu_state.flags & C_FLAG) - cpu_src++; - /* Fall through. */ - case 0: - add(bits); - break; - case 3: - if (cpu_state.flags & C_FLAG) - cpu_src++; - /* Fall through. */ - case 5: case 7: - sub(bits); - break; - case 4: - test(bits, cpu_dest, cpu_src); - break; - case 6: - bitwise(bits, (cpu_dest ^ cpu_src)); - break; - } -} - - -static void -set_sf(int bits) -{ - cpu_state.flags = (cpu_state.flags & ~0x80) | (top_bit(cpu_data, bits) ? 0x80 : 0); -} - - -static void -set_pf(void) -{ - static uint8_t table[0x100] = { - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 0, 4, 4, 0, 4, 0, 0, 4, 4, 0, 0, 4, 0, 4, 4, 0, - 4, 0, 0, 4, 0, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 4}; - - cpu_state.flags = (cpu_state.flags & ~4) | table[cpu_data & 0xff]; -} - - -static void -mul(uint16_t a, uint16_t b) -{ - int negate = 0; - int bit_count = 8; - int carry, i; - uint16_t high_bit = 0x80; - uint16_t size_mask; - uint16_t c, r; - - size_mask = (1 << bit_count) - 1; - - if (opcode != 0xd5) { - if (opcode & 1) { - bit_count = 16; - high_bit = 0x8000; - } else - wait(8, 0); - - size_mask = (1 << bit_count) - 1; - - if ((rmdat & 0x38) == 0x28) { - if (!top_bit(a, bit_count)) { - if (top_bit(b, bit_count)) { - wait(1, 0); - if ((b & size_mask) != ((opcode & 1) ? 0x8000 : 0x80)) - wait(1, 0); - b = ~b + 1; - negate = 1; - } - } else { - wait(1, 0); - a = ~a + 1; - negate = 1; - if (top_bit(b, bit_count)) { - b = ~b + 1; - negate = 0; - } else - wait(4, 0); - } - wait(10, 0); - } - wait(3, 0); - } - - c = 0; - a &= size_mask; - carry = (a & 1) != 0; - a >>= 1; - for (i = 0; i < bit_count; ++i) { - wait(7, 0); - if (carry) { - cpu_src = c; - cpu_dest = b; - add(bit_count); - c = cpu_data & size_mask; - wait(1, 0); - carry = !!(cpu_state.flags & C_FLAG); - } - r = (c >> 1) + (carry ? high_bit : 0); - carry = (c & 1) != 0; - c = r; - r = (a >> 1) + (carry ? high_bit : 0); - carry = (a & 1) != 0; - a = r; - } - if (negate) { - c = ~c; - a = (~a + 1) & size_mask; - if (a == 0) - ++c; - wait(9, 0); - } - cpu_data = a; - cpu_dest = c; - - set_sf(bit_count); - set_pf(); -} - - -static void -set_of_rotate(int bits) -{ - set_of(top_bit(cpu_data ^ cpu_dest, bits)); -} - - -static void -set_zf(int bits) -{ - int size_mask = (1 << bits) - 1; - - cpu_state.flags = (cpu_state.flags & ~0x40) | (((cpu_data & size_mask) == 0) ? 0x40 : 0); -} - - -static void -set_pzs(int bits) -{ - set_pf(); - set_zf(bits); - set_sf(bits); -} - - -static void -set_co_mul(int carry) -{ - set_cf(carry); - set_of(carry); - if (!carry) - wait(1, 0); -} - - -/* Was div(), renamed to avoid conflicts with stdlib div(). */ -static int -x86_div(uint16_t l, uint16_t h) -{ - int b, bit_count = 8; - int negative = 0; - int dividend_negative = 0; - int size_mask, carry; - uint16_t r; - - if (opcode & 1) { - l = AX; - h = DX; - bit_count = 16; - } - - size_mask = (1 << bit_count) - 1; - - if (opcode != 0xd4) { - if ((rmdat & 0x38) == 0x38) { - if (top_bit(h, bit_count)) { - h = ~h; - l = (~l + 1) & size_mask; - if (l == 0) - ++h; - h &= size_mask; - negative = 1; - dividend_negative = 1; - wait(4, 0); - } - if (top_bit(cpu_src, bit_count)) { - cpu_src = ~cpu_src + 1; - negative = !negative; - } else - wait(1, 0); - wait(9, 0); - } - wait(3, 0); - } - wait(8, 0); - cpu_src &= size_mask; - if (h >= cpu_src) { - if (opcode != 0xd4) - wait(1, 0); - interrupt(0); - return 0; - } - if (opcode != 0xd4) - wait(1, 0); - wait(2, 0); - carry = 1; - for (b = 0; b < bit_count; ++b) { - r = (l << 1) + (carry ? 1 : 0); - carry = top_bit(l, bit_count); - l = r; - r = (h << 1) + (carry ? 1 : 0); - carry = top_bit(h, bit_count); - h = r; - wait(8, 0); - if (carry) { - carry = 0; - h -= cpu_src; - if (b == bit_count - 1) - wait(2, 0); - } else { - carry = cpu_src > h; - if (!carry) { - h -= cpu_src; - wait(1, 0); - if (b == bit_count - 1) - wait(2, 0); - } - } - } - l = ~((l << 1) + (carry ? 1 : 0)); - if (opcode != 0xd4 && (rmdat & 0x38) == 0x38) { - wait(4, 0); - if (top_bit(l, bit_count)) { - if (cpu_mod == 3) - wait(1, 0); - interrupt(0); - return 0; - } - wait(7, 0); - if (negative) - l = ~l + 1; - if (dividend_negative) - h = ~h + 1; - } - if (opcode == 0xd4) { - AL = h & 0xff; - AH = l & 0xff; - } else { - AH = h & 0xff; - AL = l & 0xff; - if (opcode & 1) { - DX = h; - AX = l; - } - } - return 1; -} - - -static uint16_t -string_increment(int bits) -{ - int d = bits >> 3; - if (cpu_state.flags & D_FLAG) - cpu_state.eaaddr -= d; - else - cpu_state.eaaddr += d; - cpu_state.eaaddr &= 0xffff; - return cpu_state.eaaddr; -} - - -static void -lods(int bits) -{ - cpu_state.eaaddr = SI; - if (bits == 16) - cpu_data = readmemw((ovr_seg ? *ovr_seg : ds), cpu_state.eaaddr); - else - cpu_data = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); - SI = string_increment(bits); -} - - -static void -stos(int bits) -{ - cpu_state.eaaddr = DI; - if (bits == 16) - writememw(es, cpu_state.eaaddr, cpu_data); - else - writememb(es, cpu_state.eaaddr, (uint8_t) (cpu_data & 0xff)); - DI = string_increment(bits); -} - - -static void -da(void) -{ - set_pzs(8); - wait(2, 0); -} - - -static void -aa(void) -{ - set_of(0); - AL &= 0x0f; - wait(6, 0); -} - - -static void -set_ca(void) -{ - set_cf(1); - set_af(1); -} - - -static void -clear_ca(void) -{ - set_cf(0); - set_af(0); -} - - -static uint16_t -get_ea(void) -{ - if (opcode & 1) - return geteaw(); - else - return (uint16_t) geteab(); -} - - -static uint16_t -get_reg(uint8_t reg) -{ - if (opcode & 1) - return cpu_state.regs[reg].w; - else - return (uint16_t) getr8(reg); -} - - -static void -set_ea(uint16_t val) -{ - if (opcode & 1) - seteaw(val); - else - seteab((uint8_t) (val & 0xff)); -} - - -static void -set_reg(uint8_t reg, uint16_t val) -{ - if (opcode & 1) - cpu_state.regs[reg].w = val; - else - setr8(reg, (uint8_t) (val & 0xff)); -} - - -static void -cpu_data_opff_rm(void) { - if (!(opcode & 1)) { - if (cpu_mod != 3) - cpu_data |= 0xff00; - else - cpu_data = cpu_state.regs[cpu_rm].w; - } -} - - -/* Executes instructions up to the specified number of cycles. */ -void -execx86(int cycs) -{ - uint8_t temp = 0, temp2; - uint16_t addr, tempw; - uint16_t new_cs, new_ip; - int bits; - - cycles += cycs; - - while (cycles > 0) { - clock_start(); - - if (!repeating) { - cpu_state.oldpc = cpu_state.pc; - opcode = pfq_fetchb(); - oldc = cpu_state.flags & C_FLAG; - if (clear_lock) { - in_lock = 0; - clear_lock = 0; - } - wait(1, 0); - } - - completed = 1; - switch (opcode) { - case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */ - access(29, 16); - push(&(_opseg[(opcode >> 3) & 0x03]->seg)); - break; - case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */ - access(22, 16); - if (opcode == 0x0F) { - loadcs(pop()); - pfq_pos = 0; - } else - loadseg(pop(), _opseg[(opcode >> 3) & 0x03]); - wait(1, 0); - /* All POP segment instructions suppress interrupts for one instruction. */ - noint = 1; - break; - - case 0x26: /*ES:*/ - case 0x2E: /*CS:*/ - case 0x36: /*SS:*/ - case 0x3E: /*DS:*/ - wait(1, 0); - ovr_seg = opseg[(opcode >> 3) & 0x03]; - completed = 0; - break; - - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x38: case 0x39: case 0x3a: case 0x3b: - /* alu rm, r / r, rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(46, bits); - tempw = get_ea(); - cpu_alu_op = (opcode >> 3) & 7; - if ((opcode & 2) == 0) { - cpu_dest = tempw; - cpu_src = get_reg(cpu_reg); - } else { - cpu_dest = get_reg(cpu_reg); - cpu_src = tempw; - } - if (cpu_mod != 3) - wait(2, 0); - wait(1, 0); - alu_op(bits); - if (cpu_alu_op != 7) { - if ((opcode & 2) == 0) { - access(10, bits); - set_ea(cpu_data); - if (cpu_mod == 3) - wait(1, 0); - } else { - set_reg(cpu_reg, cpu_data); - wait(1, 0); - } - } else - wait(1, 0); - break; - - case 0x04: case 0x05: case 0x0c: case 0x0d: - case 0x14: case 0x15: case 0x1c: case 0x1d: - case 0x24: case 0x25: case 0x2c: case 0x2d: - case 0x34: case 0x35: case 0x3c: case 0x3d: - /* alu A, imm */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetch(); - cpu_dest = get_reg(0); /* AX/AL */ - cpu_src = cpu_data; - cpu_alu_op = (opcode >> 3) & 7; - alu_op(bits); - if (cpu_alu_op != 7) - set_reg(0, cpu_data); - wait(1, 0); - break; - - case 0x27: /*DAA*/ - wait(1, 0); - if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) { - cpu_data = AL + 6; - AL = (uint8_t) cpu_data; - set_af(1); - if ((cpu_data & 0x100) != 0) - set_cf(1); - } - if ((cpu_state.flags & C_FLAG) || AL > 0x9f) { - AL += 0x60; - set_cf(1); - } - da(); - break; - case 0x2F: /*DAS*/ - wait(1, 0); - temp = AL; - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - cpu_data = AL - 6; - AL = (uint8_t) cpu_data; - set_af(1); - if ((cpu_data & 0x100) != 0) - set_cf(1); - } - if ((cpu_state.flags & C_FLAG) || temp > 0x9f) { - AL -= 0x60; - set_cf(1); - } - da(); - break; - case 0x37: /*AAA*/ - wait(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - AL += 6; - ++AH; - set_ca(); - } else { - clear_ca(); - wait(1, 0); - } - aa(); - break; - case 0x3F: /*AAS*/ - wait(1, 0); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) { - AL -= 6; - --AH; - set_ca(); - } else { - clear_ca(); - wait(1, 0); - } - aa(); - break; - - case 0x40: case 0x41: case 0x42: case 0x43: - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x48: case 0x49: case 0x4A: case 0x4B: - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - /* INCDEC rw */ - wait(1, 0); - cpu_dest = cpu_state.regs[opcode & 7].w; - cpu_src = 1; - bits = 16; - if ((opcode & 8) == 0) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(16); - cpu_state.regs[opcode & 7].w = cpu_data; - break; - - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - access(30, 16); - push(&(cpu_state.regs[opcode & 0x07].w)); - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - access(23, 16); - cpu_state.regs[opcode & 0x07].w = pop(); - wait(1, 0); - break; - - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - jcc(opcode, cpu_state.flags & V_FLAG); - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - jcc(opcode, cpu_state.flags & C_FLAG); - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - jcc(opcode, cpu_state.flags & Z_FLAG); - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - jcc(opcode, cpu_state.flags & (C_FLAG | Z_FLAG)); - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - jcc(opcode, cpu_state.flags & N_FLAG); - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - jcc(opcode, cpu_state.flags & P_FLAG); - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, temp ^ temp2); - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - temp = (cpu_state.flags & N_FLAG) ? 1 : 0; - temp2 = (cpu_state.flags & V_FLAG) ? 1 : 0; - jcc(opcode, (cpu_state.flags & Z_FLAG) || (temp != temp2)); - break; - - case 0x80: case 0x81: case 0x82: case 0x83: - /* alu rm, imm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(47, bits); - cpu_data = get_ea(); - cpu_dest = cpu_data; - if (cpu_mod != 3) - wait(3, 0); - if (opcode == 0x81) { - if (cpu_mod == 3) - wait(1, 0); - cpu_src = pfq_fetchw(); - } else { - if (cpu_mod == 3) - wait(1, 0); - if (opcode == 0x83) - cpu_src = sign_extend(pfq_fetchb()); - else - cpu_src = pfq_fetchb() | 0xff00; - } - wait(1, 0); - cpu_alu_op = (rmdat & 0x38) >> 3; - alu_op(bits); - if (cpu_alu_op != 7) { - access(11, bits); - set_ea(cpu_data); - } else { - if (cpu_mod != 3) - wait(1, 0); - } - break; - - case 0x84: case 0x85: - /* TEST rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(48, bits); - cpu_data = get_ea(); - test(bits, cpu_data, get_reg(cpu_reg)); - if (cpu_mod == 3) - wait(2, 0); - wait(2, 0); - break; - case 0x86: case 0x87: - /* XCHG rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(49, bits); - cpu_data = get_ea(); - cpu_src = get_reg(cpu_reg); - set_reg(cpu_reg, cpu_data); - wait(3, 0); - access(12, bits); - set_ea(cpu_src); - break; - - case 0x88: case 0x89: - /* MOV rm, reg */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait(1, 0); - access(13, bits); - set_ea(get_reg(cpu_reg)); - break; - case 0x8A: case 0x8B: - /* MOV reg, rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(50, bits); - set_reg(cpu_reg, get_ea()); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; - - case 0x8C: /*MOV w,sreg*/ - do_mod_rm(); - if (cpu_mod == 3) - wait(1, 0); - access(14, 16); - seteaw(_opseg[(rmdat & 0x18) >> 3]->seg); - break; - - case 0x8D: /*LEA*/ - do_mod_rm(); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; - - case 0x8E: /*MOV sreg,w*/ - do_mod_rm(); - access(51, 16); - tempw = geteaw(); - if ((rmdat & 0x18) == 0x08) { - loadcs(tempw); - pfq_pos = 0; - } else - loadseg(tempw, _opseg[(rmdat & 0x18) >> 3]); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - if (((rmdat & 0x18) >> 3) == 2) - noint = 1; - break; - - case 0x8F: /*POPW*/ - do_mod_rm(); - wait(1, 0); - cpu_src = cpu_state.eaaddr; - access(24, 16); - if (cpu_mod != 3) - wait(2, 0); - cpu_data = pop(); - cpu_state.eaaddr = cpu_src; - wait(2, 0); - access(15, 16); - seteaw(cpu_data); - break; - - case 0x90: case 0x91: case 0x92: case 0x93: - case 0x94: case 0x95: case 0x96: case 0x97: - /* XCHG AX, rw */ - wait(1, 0); - cpu_data = cpu_state.regs[opcode & 7].w; - cpu_state.regs[opcode & 7].w = AX; - AX = cpu_data; - wait(1, 0); - break; - - case 0x98: /*CBW*/ - wait(1, 0); - AX = sign_extend(AL); - break; - case 0x99: /*CWD*/ - wait(4, 0); - if (!top_bit(AX, 16)) - DX = 0; - else { - wait(1, 0); - DX = 0xffff; - } - break; - case 0x9A: /*CALL FAR*/ - wait(1, 0); - new_ip = pfq_fetchw(); - wait(1, 0); - new_cs = pfq_fetchw(); - pfq_clear(); - access(31, 16); - push(&(CS)); - access(60, 16); - cpu_state.oldpc = cpu_state.pc; - loadcs(new_cs); - set_ip(new_ip); - access(32, 16); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x9B: /*WAIT*/ - if (!repeating) - wait(2, 0); - wait(5, 0); -#ifdef NO_HACK - if (irq_pending()) { - wait(7, 0); - check_interrupts(); - } else { - repeating = 1; - completed = 0; - clock_end(); - } -#else - wait(7, 0); - check_interrupts(); -#endif - break; - case 0x9C: /*PUSHF*/ - access(33, 16); - tempw = (cpu_state.flags & 0x0fd7) | 0xf000; - push(&tempw); - break; - case 0x9D: /*POPF*/ - access(25, 16); - cpu_state.flags = pop() | 2; - wait(1, 0); - break; - case 0x9E: /*SAHF*/ - wait(1, 0); - cpu_state.flags = (cpu_state.flags & 0xff02) | AH; - wait(2, 0); - break; - case 0x9F: /*LAHF*/ - wait(1, 0); - AH = cpu_state.flags & 0xd7; - break; - - case 0xA0: case 0xA1: - /* MOV A, [iw] */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(1, bits); - set_reg(0, readmem((ovr_seg ? *ovr_seg : ds))); - wait(1, 0); - break; - case 0xA2: case 0xA3: - /* MOV [iw], A */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_state.eaaddr = pfq_fetchw(); - access(7, bits); - writemem((ovr_seg ? *ovr_seg : ds), get_reg(0)); - break; - - case 0xA4: case 0xA5: /* MOVS */ - case 0xAC: case 0xAD: /* LODS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait(1, 0); - if ((opcode & 8) == 0 && in_rep != 0) - wait(1, 0); - } - if (rep_action(bits)) { - wait(1, 0); - if ((opcode & 8) != 0) - wait(1, 0); - break; - } - if (in_rep != 0 && (opcode & 8) != 0) - wait(1, 0); - access(20, bits); - lods(bits); - if ((opcode & 8) == 0) { - access(27, bits); - stos(bits); - } else { - set_reg(0, cpu_data); - if (in_rep != 0) - wait(2, 0); - } - if (in_rep == 0) { - wait(3, 0); - if ((opcode & 8) != 0) - wait(1, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xA6: case 0xA7: /* CMPS */ - case 0xAE: case 0xAF: /* SCAS */ - bits = 8 << (opcode & 1); - if (!repeating) - wait(1, 0); - if (rep_action(bits)) { - wait(2, 0); - break; - } - if (in_rep != 0) - wait(1, 0); - wait(1, 0); - cpu_dest = get_reg(0); - if ((opcode & 8) == 0) { - access(21, bits); - lods(bits); - wait(1, 0); - cpu_dest = cpu_data; - } - access(2, bits); - cpu_state.eaaddr = DI; - cpu_data = readmem(es); - DI = string_increment(bits); - cpu_src = cpu_data; - sub(bits); - wait(2, 0); - if (in_rep == 0) { - wait(3, 0); - break; - } - if ((!!(cpu_state.flags & Z_FLAG)) == (in_rep == 1)) { - completed = 1; - wait(4, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xA8: case 0xA9: - /* TEST A, imm */ - bits = 8 << (opcode & 1); - wait(1, 0); - cpu_data = pfq_fetch(); - test(bits, get_reg(0), cpu_data); - wait(1, 0); - break; - - case 0xAA: case 0xAB: /* STOS */ - bits = 8 << (opcode & 1); - if (!repeating) { - wait(1, 0); - if (in_rep != 0) - wait(1, 0); - } - if (rep_action(bits)) { - wait(1, 0); - break; - } - cpu_data = AX; - access(28, bits); - stos(bits); - if (in_rep == 0) { - wait(3, 0); - break; - } - repeating = 1; - clock_end(); - break; - - case 0xB0: case 0xB1: case 0xB2: case 0xB3: /*MOV cpu_reg,#8*/ - case 0xB4: case 0xB5: case 0xB6: case 0xB7: - wait(1, 0); - if (opcode & 0x04) - cpu_state.regs[opcode & 0x03].b.h = pfq_fetchb(); - else - cpu_state.regs[opcode & 0x03].b.l = pfq_fetchb(); - wait(1, 0); - break; - - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - wait(1, 0); - cpu_state.regs[opcode & 0x07].w = pfq_fetchw(); - wait(1, 0); - break; - - case 0xC0: case 0xC1: case 0xC2: case 0xC3: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - /* RET */ - bits = 8 + (opcode & 0x08); - if ((opcode & 9) != 1) - wait(1, 0); - if (!(opcode & 1)) { - cpu_src = pfq_fetchw(); - wait(1, 0); - } - if ((opcode & 9) == 9) - wait(1, 0); - pfq_clear(); - access(26, bits); - new_ip = pop(); - wait(2, 0); - if ((opcode & 8) == 0) - new_cs = CS; - else { - access(42, bits); - new_cs = pop(); - if (opcode & 1) - wait(1, 0); - } - if (!(opcode & 1)) { - SP += cpu_src; - wait(1, 0); - } - loadcs(new_cs); - access(72, bits); - set_ip(new_ip); - break; - - case 0xC4: case 0xC5: - /* LsS rw, rmd */ - do_mod_rm(); - bits = 16; - access(52, bits); - read_ea(1, bits); - cpu_state.regs[cpu_reg].w = cpu_data; - access(57, bits); - read_ea2(bits); - loadseg(cpu_data, (opcode & 0x01) ? &cpu_state.seg_ds : &cpu_state.seg_es); - wait(1, 0); - break; - - case 0xC6: case 0xC7: - /* MOV rm, imm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - cpu_data = pfq_fetch(); - if (cpu_mod == 3) - wait(1, 0); - access(16, bits); - set_ea(cpu_data); - break; - - case 0xCC: /*INT 3*/ - interrupt(3); - break; - case 0xCD: /*INT*/ - wait(1, 0); - interrupt(pfq_fetchb()); - break; - case 0xCE: /*INTO*/ - wait(3, 0); - if (cpu_state.flags & V_FLAG) { - wait(2, 0); - interrupt(4); - } - break; - - case 0xCF: /*IRET*/ - access(43, 8); - new_ip = pop(); - wait(3, 0); - access(44, 8); - new_cs = pop(); - loadcs(new_cs); - access(62, 8); - set_ip(new_ip); - access(45, 8); - cpu_state.flags = pop() | 2; - wait(5, 0); - noint = 1; - nmi_enable = 1; - break; - - case 0xD0: case 0xD1: case 0xD2: case 0xD3: - /* rot rm */ - bits = 8 << (opcode & 1); - do_mod_rm(); - if (cpu_mod == 3) - wait(1, 0); - access(53, bits); - cpu_data = get_ea(); - if ((opcode & 2) == 0) { - cpu_src = 1; - wait((cpu_mod != 3) ? 4 : 0, 0); - } else { - cpu_src = CL; - wait((cpu_mod != 3) ? 9 : 6, 0); - } - while (cpu_src != 0) { - cpu_dest = cpu_data; - oldc = cpu_state.flags & C_FLAG; - switch (rmdat & 0x38) { - case 0x00: /* ROL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0); - set_of_rotate(bits); - break; - case 0x08: /* ROR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (cpu_state.flags & C_FLAG) - cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000); - set_of_rotate(bits); - break; - case 0x10: /* RCL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data = (cpu_data << 1) | (oldc ? 1 : 0); - set_of_rotate(bits); - break; - case 0x18: /* RCR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (oldc) - cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000); - set_cf((cpu_dest & 1) != 0); - set_of_rotate(bits); - break; - case 0x20: /* SHL */ - set_cf(top_bit(cpu_data, bits)); - cpu_data <<= 1; - set_of_rotate(bits); - set_pzs(bits); - break; - case 0x28: /* SHR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - set_of_rotate(bits); - set_af(1); - set_pzs(bits); - break; - case 0x30: /* SETMO - undocumented? */ - bitwise(bits, 0xffff); - set_cf(0); - set_of_rotate(bits); - set_af(0); - set_pzs(bits); - break; - case 0x38: /* SAR */ - set_cf((cpu_data & 1) != 0); - cpu_data >>= 1; - if (!(opcode & 1)) - cpu_data |= (cpu_dest & 0x80); - else - cpu_data |= (cpu_dest & 0x8000); - set_of_rotate(bits); - set_af(1); - set_pzs(bits); - break; - } - if ((opcode & 2) != 0) - wait(4, 0); - --cpu_src; - } - access(17, bits); - set_ea(cpu_data); - break; - - case 0xD4: /*AAM*/ - wait(1, 0); - cpu_src = pfq_fetchb(); - if (x86_div(AL, 0)) - set_pzs(16); - break; - case 0xD5: /*AAD*/ - wait(1, 0); - mul(pfq_fetchb(), AH); - AL += cpu_data; - AH = 0x00; - set_pzs(16); - break; - case 0xD6: /*SALC*/ - wait(1, 0); - AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00; - wait(1, 0); - break; - case 0xD7: /*XLATB*/ - cpu_state.eaaddr = (BX + AL) & 0xffff; - access(4, 8); - AL = readmemb((ovr_seg ? *ovr_seg : ds) + cpu_state.eaaddr); - wait(1, 0); - break; - - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDD: case 0xDC: case 0xDE: case 0xDF: - /* esc i, r, rm */ - do_mod_rm(); - access(54, 16); - tempw = cpu_state.pc; - if (!hasfpu) - geteaw(); - else switch(opcode) { - case 0xD8: - ops_fpu_8087_d8[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); - break; - case 0xD9: - ops_fpu_8087_d9[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDA: - ops_fpu_8087_da[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDB: - ops_fpu_8087_db[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDC: - ops_fpu_8087_dc[(rmdat >> 3) & 0x1f]((uint32_t) rmdat); - break; - case 0xDD: - ops_fpu_8087_dd[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDE: - ops_fpu_8087_de[rmdat & 0xff]((uint32_t) rmdat); - break; - case 0xDF: - ops_fpu_8087_df[rmdat & 0xff]((uint32_t) rmdat); - break; - } - cpu_state.pc = tempw; /* Do this as the x87 code advances it, which is needed on - the 286+ core, but not here. */ - wait(1, 0); - if (cpu_mod != 3) - wait(2, 0); - break; - - case 0xE0: case 0xE1: case 0xE2: case 0xE3: - /* LOOP */ - wait(3, 0); - cpu_data = pfq_fetchb(); - if (opcode != 0xe2) - wait(1, 0); - if (opcode != 0xe3) { - --CX; - oldc = (CX != 0); - switch (opcode) { - case 0xE0: - if (cpu_state.flags & Z_FLAG) - oldc = 0; - break; - case 0xE1: - if (!(cpu_state.flags & Z_FLAG)) - oldc = 0; - break; - } - } else - oldc = (CX == 0); - if (oldc) - jump_short(); - break; - - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xEC: case 0xED: case 0xEE: case 0xEF: - bits = 8 << (opcode & 1); - if ((opcode & 0x0e) != 0x0c) - wait(1, 0); - if ((opcode & 8) == 0) - cpu_data = pfq_fetchb(); - else - cpu_data = DX; - cpu_state.eaaddr = cpu_data; - if ((opcode & 2) == 0) { - access(3, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { - AX = inw(cpu_data); - wait(4, 1); /* I/O access and wait state. */ - } else { - AL = inb(cpu_data); - if (opcode & 1) - AH = inb(cpu_data + 1); - wait(bits >> 1, 1); /* I/O access. */ - } - wait(1, 0); - } else { - if ((opcode & 8) == 0) - access(8, bits); - else - access(9, bits); - if ((opcode & 1) && is8086 && !(cpu_data & 1)) { - outw(cpu_data, AX); - wait(4, 1); - } else { - outb(cpu_data, AL); - if (opcode & 1) - outb(cpu_data + 1, AH); - wait(bits >> 1, 1); /* I/O access. */ - } - } - break; - - case 0xE8: /*CALL rel 16*/ - wait(1, 0); - cpu_state.oldpc = jump_near(); - access(34, 8); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0xE9: /*JMP rel 16*/ - wait(1, 0); - jump_near(); - break; - case 0xEA: /*JMP far*/ - wait(1, 0); - addr = pfq_fetchw(); - wait(1, 0); - tempw = pfq_fetchw(); - loadcs(tempw); - access(70, 8); - pfq_clear(); - set_ip(addr); - break; - case 0xEB: /*JMP rel*/ - wait(1, 0); - cpu_data = (int8_t) pfq_fetchb(); - jump_short(); - wait(1, 0); - break; - - case 0xF0: case 0xF1: /*LOCK - F1 is alias*/ - in_lock = 1; - wait(1, 0); - completed = 0; - break; - - case 0xF2: /*REPNE*/ - case 0xF3: /*REPE*/ - wait(1, 0); - in_rep = (opcode == 0xf2 ? 1 : 2); - completed = 0; - break; - - case 0xF4: /*HLT*/ - if (!repeating) { - wait(1, 0); - pfq_clear(); - } - wait(1, 0); - if (irq_pending()) { - wait(cycles & 1, 0); - check_interrupts(); - } else { - repeating = 1; - completed = 0; - clock_end(); - } - break; - case 0xF5: /*CMC*/ - wait(1, 0); - cpu_state.flags ^= C_FLAG; - break; - - case 0xF6: case 0xF7: - bits = 8 << (opcode & 1); - do_mod_rm(); - access(55, bits); - cpu_data = get_ea(); - switch (rmdat & 0x38) { - case 0x00: case 0x08: - /* TEST */ - wait(2, 0); - if (cpu_mod != 3) - wait(1, 0); - cpu_src = pfq_fetch(); - wait(1, 0); - test(bits, cpu_data, cpu_src); - if (cpu_mod != 3) - wait(1, 0); - break; - case 0x10: /* NOT */ - case 0x18: /* NEG */ - wait(2, 0); - if ((rmdat & 0x38) == 0x10) - cpu_data = ~cpu_data; - else { - cpu_src = cpu_data; - cpu_dest = 0; - sub(bits); - } - access(18, bits); - set_ea(cpu_data); - break; - case 0x20: /* MUL */ - case 0x28: /* IMUL */ - wait(1, 0); - if (opcode & 1) { - 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)); - } 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)); - } - /* NOTE: When implementing the V20, care should be taken to not change - the zero flag. */ - set_zf(bits); - if (cpu_mod != 3) - wait(1, 0); - break; - case 0x30: /* DIV */ - case 0x38: /* IDIV */ - if (cpu_mod != 3) - wait(1, 0); - cpu_src = cpu_data; - if (x86_div(AL, AH)) - wait(1, 0); - break; - } - break; - - case 0xF8: case 0xF9: - /* CLCSTC */ - wait(1, 0); - set_cf(opcode & 1); - break; - case 0xFA: case 0xFB: - /* CLISTI */ - wait(1, 0); - set_if(opcode & 1); - break; - case 0xFC: case 0xFD: - /* CLDSTD */ - wait(1, 0); - set_df(opcode & 1); - break; - - case 0xFE: case 0xFF: - /* misc */ - bits = 8 << (opcode & 1); - do_mod_rm(); - access(56, bits); - read_ea(((rmdat & 0x38) == 0x18) || ((rmdat & 0x38) == 0x28), bits); - switch (rmdat & 0x38) { - case 0x00: /* INC rm */ - case 0x08: /* DEC rm */ - cpu_dest = cpu_data; - cpu_src = 1; - if ((rmdat & 0x38) == 0x00) { - cpu_data = cpu_dest + cpu_src; - set_of_add(bits); - } else { - cpu_data = cpu_dest - cpu_src; - set_of_sub(bits); - } - do_af(); - set_pzs(bits); - wait(2, 0); - access(19, bits); - set_ea(cpu_data); - break; - case 0x10: /* CALL rm */ - cpu_data_opff_rm(); - access(63, bits); - wait(1, 0); - pfq_clear(); - wait(4, 0); - if (cpu_mod != 3) - wait(1, 0); - wait(1, 0); /* Wait. */ - cpu_state.oldpc = cpu_state.pc; - set_ip(cpu_data); - wait(2, 0); - access(35, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x18: /* CALL rmd */ - new_ip = cpu_data; - access(58, bits); - read_ea2(bits); - if (!(opcode & 1)) - cpu_data |= 0xff00; - new_cs = cpu_data; - access(36, bits); - push(&(CS)); - access(64, bits); - wait(4, 0); - cpu_state.oldpc = cpu_state.pc; - loadcs(new_cs); - set_ip(new_ip); - access(37, bits); - push((uint16_t *) &(cpu_state.oldpc)); - break; - case 0x20: /* JMP rm */ - cpu_data_opff_rm(); - access(65, bits); - set_ip(cpu_data); - break; - case 0x28: /* JMP rmd */ - new_ip = cpu_data; - access(59, bits); - read_ea2(bits); - if (!(opcode & 1)) - cpu_data |= 0xff00; - new_cs = cpu_data; - loadcs(new_cs); - access(66, bits); - set_ip(new_ip); - break; - case 0x30: /* PUSH rm */ - case 0x38: - if (cpu_mod != 3) - wait(1, 0); - access(38, bits); - push(&(cpu_data)); - break; - } - break; - - default: - x808x_log("Illegal opcode: %02X\n", opcode); - pfq_fetchb(); - wait(8, 0); - break; - } - - if (completed) { - repeating = 0; - ovr_seg = NULL; - in_rep = 0; - if (in_lock) - clear_lock = 1; - clock_end(); - check_interrupts(); - - if (noint) - noint = 0; - } - - ins++; - } -} diff --git a/src/cpu_new/codegen.c b/src/cpu_new/codegen.c index 243f61791..9758788b1 100644 --- a/src/cpu_new/codegen.c +++ b/src/cpu_new/codegen.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86_ops.h" #include "codegen.h" diff --git a/src/cpu_new/codegen.h b/src/cpu_new/codegen.h index d4f2563f6..039a34c0f 100644 --- a/src/cpu_new/codegen.h +++ b/src/cpu_new/codegen.h @@ -2,7 +2,7 @@ #define _CODEGEN_H_ #include "mem.h" -#include "x86_ops.h" +#include "../cpu_common/x86_ops.h" /*Handling self-modifying code (of which there is a lot on x86) : diff --git a/src/cpu_new/codegen_accumulate.c b/src/cpu_new/codegen_accumulate.c index c9b85ba78..726f5258f 100644 --- a/src/cpu_new/codegen_accumulate.c +++ b/src/cpu_new/codegen_accumulate.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_accumulate.h" diff --git a/src/cpu_new/codegen_allocator.c b/src/cpu_new/codegen_allocator.c index b78c4df12..9f5d87852 100644 --- a/src/cpu_new/codegen_allocator.c +++ b/src/cpu_new/codegen_allocator.c @@ -9,9 +9,9 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_arm.c b/src/cpu_new/codegen_backend_arm.c index ddabbb5c5..8ad2d0011 100644 --- a/src/cpu_new/codegen_backend_arm.c +++ b/src/cpu_new/codegen_backend_arm.c @@ -2,9 +2,9 @@ #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_arm64.c b/src/cpu_new/codegen_backend_arm64.c index 32489000f..1cfd27d9e 100644 --- a/src/cpu_new/codegen_backend_arm64.c +++ b/src/cpu_new/codegen_backend_arm64.c @@ -2,9 +2,9 @@ #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_arm64_ops.c b/src/cpu_new/codegen_backend_arm64_ops.c index 44cf87647..f55b0d569 100644 --- a/src/cpu_new/codegen_backend_arm64_ops.c +++ b/src/cpu_new/codegen_backend_arm64_ops.c @@ -1,9 +1,9 @@ #ifdef __aarch64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_arm64_uops.c b/src/cpu_new/codegen_backend_arm64_uops.c index e9cf28684..b7cf12023 100644 --- a/src/cpu_new/codegen_backend_arm64_uops.c +++ b/src/cpu_new/codegen_backend_arm64_uops.c @@ -1,9 +1,9 @@ #ifdef __aarch64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x87.h" diff --git a/src/cpu_new/codegen_backend_arm_ops.c b/src/cpu_new/codegen_backend_arm_ops.c index 1b2ef28f3..4bb86c2e7 100644 --- a/src/cpu_new/codegen_backend_arm_ops.c +++ b/src/cpu_new/codegen_backend_arm_ops.c @@ -1,9 +1,9 @@ #ifdef __ARM_EABI__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_arm_uops.c b/src/cpu_new/codegen_backend_arm_uops.c index 1dbaab407..0ef7ed7eb 100644 --- a/src/cpu_new/codegen_backend_arm_uops.c +++ b/src/cpu_new/codegen_backend_arm_uops.c @@ -2,9 +2,9 @@ #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x87.h" diff --git a/src/cpu_new/codegen_backend_x86-64.c b/src/cpu_new/codegen_backend_x86-64.c index 4615aa381..d93fce248 100644 --- a/src/cpu_new/codegen_backend_x86-64.c +++ b/src/cpu_new/codegen_backend_x86-64.c @@ -1,9 +1,9 @@ #ifdef __amd64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_x86-64_ops.c b/src/cpu_new/codegen_backend_x86-64_ops.c index 74173e626..dc1718892 100644 --- a/src/cpu_new/codegen_backend_x86-64_ops.c +++ b/src/cpu_new/codegen_backend_x86-64_ops.c @@ -1,9 +1,9 @@ #ifdef __amd64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" @@ -1018,7 +1018,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ diff --git a/src/cpu_new/codegen_backend_x86-64_ops_sse.c b/src/cpu_new/codegen_backend_x86-64_ops_sse.c index b8177648e..3a74910f2 100644 --- a/src/cpu_new/codegen_backend_x86-64_ops_sse.c +++ b/src/cpu_new/codegen_backend_x86-64_ops_sse.c @@ -1,9 +1,9 @@ #ifdef __amd64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_x86-64_uops.c b/src/cpu_new/codegen_backend_x86-64_uops.c index bff4e3775..f497aa569 100644 --- a/src/cpu_new/codegen_backend_x86-64_uops.c +++ b/src/cpu_new/codegen_backend_x86-64_uops.c @@ -1,9 +1,9 @@ #ifdef __amd64__ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x87.h" diff --git a/src/cpu_new/codegen_backend_x86.c b/src/cpu_new/codegen_backend_x86.c index d83d99af0..d364b7634 100644 --- a/src/cpu_new/codegen_backend_x86.c +++ b/src/cpu_new/codegen_backend_x86.c @@ -3,9 +3,9 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_x86_ops.c b/src/cpu_new/codegen_backend_x86_ops.c index 18f0171a5..766ce0fc6 100644 --- a/src/cpu_new/codegen_backend_x86_ops.c +++ b/src/cpu_new/codegen_backend_x86_ops.c @@ -1,9 +1,9 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" @@ -763,7 +763,7 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/ codegen_addlong(block, imm_data); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 8); codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/ diff --git a/src/cpu_new/codegen_backend_x86_ops_fpu.c b/src/cpu_new/codegen_backend_x86_ops_fpu.c index dd1e658fb..03734ca90 100644 --- a/src/cpu_new/codegen_backend_x86_ops_fpu.c +++ b/src/cpu_new/codegen_backend_x86_ops_fpu.c @@ -1,9 +1,9 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_backend_x86_ops_sse.c b/src/cpu_new/codegen_backend_x86_ops_sse.c index 641d16532..83a54f64a 100644 --- a/src/cpu_new/codegen_backend_x86_ops_sse.c +++ b/src/cpu_new/codegen_backend_x86_ops_sse.c @@ -1,9 +1,9 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" @@ -204,7 +204,7 @@ void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/ codegen_addbyte(block, 0x24); } - else if (offset >= -80 || offset < 0x80) + else if (offset >= -0x80 && offset < 0x80) { codegen_alloc_bytes(block, 6); codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/ diff --git a/src/cpu_new/codegen_backend_x86_uops.c b/src/cpu_new/codegen_backend_x86_uops.c index 679a7b77b..af801382c 100644 --- a/src/cpu_new/codegen_backend_x86_uops.c +++ b/src/cpu_new/codegen_backend_x86_uops.c @@ -1,9 +1,9 @@ #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu_new/codegen_block.c b/src/cpu_new/codegen_block.c index acff96a92..eec6d467c 100644 --- a/src/cpu_new/codegen_block.c +++ b/src/cpu_new/codegen_block.c @@ -1,8 +1,9 @@ #include #include -#include "../86box.h" +#include +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ir.c b/src/cpu_new/codegen_ir.c index 7d305737b..6aa2e6546 100644 --- a/src/cpu_new/codegen_ir.c +++ b/src/cpu_new/codegen_ir.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_allocator.h" diff --git a/src/cpu_new/codegen_ops.c b/src/cpu_new/codegen_ops.c index c1c6e54e7..2870c2b72 100644 --- a/src/cpu_new/codegen_ops.c +++ b/src/cpu_new/codegen_ops.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_ir.h" diff --git a/src/cpu_new/codegen_ops_3dnow.c b/src/cpu_new/codegen_ops_3dnow.c index 2406fe8e0..c2c0e85a6 100644 --- a/src/cpu_new/codegen_ops_3dnow.c +++ b/src/cpu_new/codegen_ops_3dnow.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_arith.c b/src/cpu_new/codegen_ops_arith.c index 70eddd4a9..f2c85eeba 100644 --- a/src/cpu_new/codegen_ops_arith.c +++ b/src/cpu_new/codegen_ops_arith.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_branch.c b/src/cpu_new/codegen_ops_branch.c index 5bea31781..853b0308a 100644 --- a/src/cpu_new/codegen_ops_branch.c +++ b/src/cpu_new/codegen_ops_branch.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "386_common.h" diff --git a/src/cpu_new/codegen_ops_fpu_arith.c b/src/cpu_new/codegen_ops_fpu_arith.c index 3f5621c3c..99384b3d4 100644 --- a/src/cpu_new/codegen_ops_fpu_arith.c +++ b/src/cpu_new/codegen_ops_fpu_arith.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_fpu_constant.c b/src/cpu_new/codegen_ops_fpu_constant.c index bca268ee3..cb048547c 100644 --- a/src/cpu_new/codegen_ops_fpu_constant.c +++ b/src/cpu_new/codegen_ops_fpu_constant.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_fpu_loadstore.c b/src/cpu_new/codegen_ops_fpu_loadstore.c index 599ab800e..879760518 100644 --- a/src/cpu_new/codegen_ops_fpu_loadstore.c +++ b/src/cpu_new/codegen_ops_fpu_loadstore.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_fpu_misc.c b/src/cpu_new/codegen_ops_fpu_misc.c index 7de92a39c..cb54ce791 100644 --- a/src/cpu_new/codegen_ops_fpu_misc.c +++ b/src/cpu_new/codegen_ops_fpu_misc.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_helpers.c b/src/cpu_new/codegen_ops_helpers.c index 9fc754e6c..feae979bb 100644 --- a/src/cpu_new/codegen_ops_helpers.c +++ b/src/cpu_new/codegen_ops_helpers.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "386_common.h" diff --git a/src/cpu_new/codegen_ops_jump.c b/src/cpu_new/codegen_ops_jump.c index 4363c9040..2e304abc3 100644 --- a/src/cpu_new/codegen_ops_jump.c +++ b/src/cpu_new/codegen_ops_jump.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "386_common.h" @@ -13,7 +13,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); + int32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc); uint32_t dest_addr = op_pc+1+offset; if (!(op_32 & 0x100)) @@ -26,7 +26,7 @@ uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t f } uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); + int32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc); uint32_t dest_addr = op_pc+2+offset; dest_addr &= 0xffff; @@ -38,7 +38,7 @@ uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t } uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) { - uint32_t offset = fastreadl(cs + op_pc); + int32_t offset = fastreadl(cs + op_pc); uint32_t dest_addr = op_pc+4+offset; if (offset < 0) diff --git a/src/cpu_new/codegen_ops_logic.c b/src/cpu_new/codegen_ops_logic.c index 87607ab2d..372fb2e60 100644 --- a/src/cpu_new/codegen_ops_logic.c +++ b/src/cpu_new/codegen_ops_logic.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_misc.c b/src/cpu_new/codegen_ops_misc.c index 3896e7ebc..eb73a4f81 100644 --- a/src/cpu_new/codegen_ops_misc.c +++ b/src/cpu_new/codegen_ops_misc.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" @@ -359,11 +359,11 @@ uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return -1; case 0x28: /*JMP far*/ + uop_MOVZX(ir, IREG_pc, src_reg); uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); uop_CALL_FUNC(ir, loadcsjmp); - uop_MOVZX(ir, IREG_pc, src_reg); return -1; case 0x30: /*PUSH*/ @@ -466,11 +466,11 @@ uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe return -1; case 0x28: /*JMP far*/ + uop_MOV(ir, IREG_pc, src_reg); uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W); - uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc); + uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 1); uop_CALL_FUNC(ir, loadcsjmp); - uop_MOV(ir, IREG_pc, src_reg); return -1; case 0x30: /*PUSH*/ diff --git a/src/cpu_new/codegen_ops_mmx_arith.c b/src/cpu_new/codegen_ops_mmx_arith.c index 6b42273fa..91c6a61d0 100644 --- a/src/cpu_new/codegen_ops_mmx_arith.c +++ b/src/cpu_new/codegen_ops_mmx_arith.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mmx_cmp.c b/src/cpu_new/codegen_ops_mmx_cmp.c index 649e8550f..187f15fc4 100644 --- a/src/cpu_new/codegen_ops_mmx_cmp.c +++ b/src/cpu_new/codegen_ops_mmx_cmp.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mmx_loadstore.c b/src/cpu_new/codegen_ops_mmx_loadstore.c index 37ab3199a..a4413478e 100644 --- a/src/cpu_new/codegen_ops_mmx_loadstore.c +++ b/src/cpu_new/codegen_ops_mmx_loadstore.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mmx_logic.c b/src/cpu_new/codegen_ops_mmx_logic.c index 4a554b238..3bd78ec70 100644 --- a/src/cpu_new/codegen_ops_mmx_logic.c +++ b/src/cpu_new/codegen_ops_mmx_logic.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mmx_pack.c b/src/cpu_new/codegen_ops_mmx_pack.c index 6e9616271..9f1ae7aed 100644 --- a/src/cpu_new/codegen_ops_mmx_pack.c +++ b/src/cpu_new/codegen_ops_mmx_pack.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mmx_shift.c b/src/cpu_new/codegen_ops_mmx_shift.c index 014001d53..4f99050d5 100644 --- a/src/cpu_new/codegen_ops_mmx_shift.c +++ b/src/cpu_new/codegen_ops_mmx_shift.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_mov.c b/src/cpu_new/codegen_ops_mov.c index 87d7bc8bb..d6bfc85b6 100644 --- a/src/cpu_new/codegen_ops_mov.c +++ b/src/cpu_new/codegen_ops_mov.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "386_common.h" diff --git a/src/cpu_new/codegen_ops_shift.c b/src/cpu_new/codegen_ops_shift.c index 2d0b760d2..c3d5db504 100644 --- a/src/cpu_new/codegen_ops_shift.c +++ b/src/cpu_new/codegen_ops_shift.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_ops_stack.c b/src/cpu_new/codegen_ops_stack.c index 28b346446..eb1f4d18e 100644 --- a/src/cpu_new/codegen_ops_stack.c +++ b/src/cpu_new/codegen_ops_stack.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_flags.h" diff --git a/src/cpu_new/codegen_reg.c b/src/cpu_new/codegen_reg.c index 70b654998..b5af4a050 100644 --- a/src/cpu_new/codegen_reg.c +++ b/src/cpu_new/codegen_reg.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_backend.h" diff --git a/src/cpu_new/codegen_timing_486.c b/src/cpu_new/codegen_timing_486.c index 6b744472b..970514f29 100644 --- a/src/cpu_new/codegen_timing_486.c +++ b/src/cpu_new/codegen_timing_486.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_ops.h" @@ -358,7 +358,7 @@ void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uin { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_686.c b/src/cpu_new/codegen_timing_686.c index 6bcb7c44d..58afb7262 100644 --- a/src/cpu_new/codegen_timing_686.c +++ b/src/cpu_new/codegen_timing_686.c @@ -10,9 +10,9 @@ */ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_ops.h" @@ -885,7 +885,7 @@ void codegen_timing_686_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, uin { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_common.c b/src/cpu_new/codegen_timing_common.c index 3b47a2734..5eaa7f532 100644 --- a/src/cpu_new/codegen_timing_common.c +++ b/src/cpu_new/codegen_timing_common.c @@ -1,7 +1,7 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "codegen_timing_common.h" diff --git a/src/cpu_new/codegen_timing_k6.c b/src/cpu_new/codegen_timing_k6.c index 9c216de9a..5aa05cb87 100644 --- a/src/cpu_new/codegen_timing_k6.c +++ b/src/cpu_new/codegen_timing_k6.c @@ -1,10 +1,10 @@ /*Most of the vector instructions here are a total guess. Some of the timings are based on http://users.atw.hu/instlatx64/AuthenticAMD0000562_K6_InstLatX86.txt*/ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" -#include "../machine/machine.h" +#include "mem.h" +#include "machine.h" #include "x86.h" #include "x86_ops.h" diff --git a/src/cpu_new/codegen_timing_pentium.c b/src/cpu_new/codegen_timing_pentium.c index ee893a361..f923646a6 100644 --- a/src/cpu_new/codegen_timing_pentium.c +++ b/src/cpu_new/codegen_timing_pentium.c @@ -11,12 +11,12 @@ */ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_ops.h" @@ -1136,7 +1136,7 @@ void codegen_timing_pentium_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_winchip.c b/src/cpu_new/codegen_timing_winchip.c index 90982349f..53159a375 100644 --- a/src/cpu_new/codegen_timing_winchip.c +++ b/src/cpu_new/codegen_timing_winchip.c @@ -1,10 +1,10 @@ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" #include "x86.h" #include "x86_ops.h" #include "x87.h" -#include "../mem.h" +#include "mem.h" #include "codegen.h" #include "codegen_ops.h" @@ -358,7 +358,7 @@ void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32, { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/codegen_timing_winchip2.c b/src/cpu_new/codegen_timing_winchip2.c index 9da156b82..360683522 100644 --- a/src/cpu_new/codegen_timing_winchip2.c +++ b/src/cpu_new/codegen_timing_winchip2.c @@ -8,9 +8,9 @@ - Instructions with prefixes can pair if both instructions are fully decoded when the first instruction starts execution.*/ #include -#include "../86box.h" +#include "86box.h" #include "cpu.h" -#include "../mem.h" +#include "mem.h" #include "x86.h" #include "x86_ops.h" @@ -626,7 +626,7 @@ static void codegen_timing_winchip2_opcode(uint8_t opcode, uint32_t fetchdat, in { case 0x80: case 0x82: case 0x83: timings = mod3 ? opcode_timings_8x_mod3 : opcode_timings_8x; - deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x_mod3; + deps = mod3 ? opcode_deps_8x_mod3 : opcode_deps_8x; opcode = (fetchdat >> 3) & 7; break; case 0x81: diff --git a/src/cpu_new/cpu.h b/src/cpu_new/cpu.h deleted file mode 100644 index 6bf8c9a58..000000000 --- a/src/cpu_new/cpu.h +++ /dev/null @@ -1,504 +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. - * - * CPU type handler. - * - * Version: @(#)cpu.h 1.0.13 2018/11/14 - * - * Authors: Sarah Walker, - * leilei, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 leilei. - * Copyright 2016,2018 Miran Grca. - */ -#ifndef EMU_CPU_H -# define EMU_CPU_H - - -#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_WINCHIP2 20 -#define CPU_PENTIUM 21 -#define CPU_PENTIUMMMX 22 -#define CPU_Cx6x86 23 -#define CPU_Cx6x86MX 24 -#define CPU_Cx6x86L 25 -#define CPU_CxGX1 26 -#define CPU_K5 27 -#define CPU_5K86 28 -#define CPU_K6 29 -#define CPU_K6_2 30 -#define CPU_K6_3 31 -#define CPU_K6_2P 32 -#define CPU_K6_3P 33 -#define CPU_PENTIUMPRO 34 /* 686 class CPUs */ -#define CPU_PENTIUM2D 35 - -#define MANU_INTEL 0 -#define MANU_AMD 1 -#define MANU_CYRIX 2 -#define MANU_IDT 3 - -#define CPU_SUPPORTS_DYNAREC 1 -#define CPU_REQUIRES_DYNAREC 2 -#define CPU_ALTERNATE_XTAL 4 - - -typedef struct { - const char*name; - int cpu_type; - int rspeed; - double multi; - int pci_speed; - uint32_t edx_reset; - uint32_t cpuid_model; - uint16_t cyrix_id; - uint8_t cpu_flags; - int8_t mem_read_cycles, mem_write_cycles; - int8_t cache_read_cycles, cache_write_cycles; - int8_t atclk_div; -} CPU; - -extern CPU cpus_8088[]; -extern CPU cpus_8086[]; -extern CPU cpus_286[]; -extern CPU cpus_i386SX[]; -extern CPU cpus_i386DX[]; -extern CPU cpus_Am386SX[]; -extern CPU cpus_Am386DX[]; -extern CPU cpus_486SLC[]; -extern CPU cpus_486DLC[]; -extern CPU cpus_IBM386SLC[]; -extern CPU cpus_IBM486SLC[]; -extern CPU cpus_IBM486BL[]; -extern CPU cpus_i486S1[]; -extern CPU cpus_Am486S1[]; -extern CPU cpus_Cx486S1[]; -extern CPU cpus_i486[]; -extern CPU cpus_Am486[]; -extern CPU cpus_Cx486[]; -extern CPU cpus_WinChip[]; -extern CPU cpus_WinChip_SS7[]; -extern CPU cpus_Pentium5V[]; -extern CPU cpus_Pentium5V50[]; -extern CPU cpus_PentiumS5[]; -extern CPU cpus_Pentium3V[]; -extern CPU cpus_K5[]; -extern CPU cpus_K56[]; -extern CPU cpus_K56_SS7[]; -extern CPU cpus_Pentium[]; -extern CPU cpus_6x863V[]; -extern CPU cpus_6x86[]; -extern CPU cpus_6x86SS7[]; -#ifdef DEV_BRANCH -#ifdef USE_I686 -extern CPU cpus_PentiumPro[]; -extern CPU cpus_Pentium2[]; -extern CPU cpus_Pentium2D[]; -#endif -#endif - - -#define C_FLAG 0x0001 -#define P_FLAG 0x0004 -#define A_FLAG 0x0010 -#define Z_FLAG 0x0040 -#define N_FLAG 0x0080 -#define T_FLAG 0x0100 -#define I_FLAG 0x0200 -#define D_FLAG 0x0400 -#define V_FLAG 0x0800 -#define NT_FLAG 0x4000 - -#define VM_FLAG 0x0002 /* in EFLAGS */ -#define VIF_FLAG 0x0008 /* in EFLAGS */ -#define VIP_FLAG 0x0010 /* in EFLAGS */ - -#define WP_FLAG 0x10000 /* in CR0 */ -#define CR4_VME (1 << 0) -#define CR4_PVI (1 << 1) -#define CR4_PSE (1 << 4) - -#define CPL ((cpu_state.seg_cs.access>>5)&3) - -#define IOPL ((cpu_state.flags>>12)&3) - -#define IOPLp ((!(msw&1)) || (CPL<=IOPL)) - - -typedef union { - uint32_t l; - uint16_t w; - struct { - uint8_t l, - h; - } b; -} x86reg; - -typedef struct { - uint32_t base; - uint32_t limit; - uint8_t access; - uint16_t seg; - uint32_t limit_low, - limit_high; - int checked; /*Non-zero if selector is known to be valid*/ -} x86seg; - -typedef union { - uint64_t q; - int64_t sq; - uint32_t l[2]; - int32_t sl[2]; - uint16_t w[4]; - int16_t sw[4]; - uint8_t b[8]; - int8_t sb[8]; - float f[2]; -} MMX_REG; - -typedef struct { - uint32_t tr1, tr12; - uint32_t cesr; - uint32_t fcr; - uint64_t fcr2, fcr3; -} msr_t; - -typedef union { - uint32_t l; - uint16_t w; -} cr0_t; - - -struct _cpustate_ { - x86reg regs[8]; - - uint8_t tag[8]; - - x86seg *ea_seg; - uint32_t eaaddr; - - int flags_op; - uint32_t flags_res; - uint32_t flags_op1, - flags_op2; - - uint32_t pc; - uint32_t oldpc; - uint32_t op32; - - int TOP; - - union { - struct { - int8_t rm, - mod, - reg; - } rm_mod_reg; - int32_t rm_mod_reg_data; - } rm_data; - - int8_t ssegs; - int8_t ismmx; - int8_t abrt; - - int _cycles; - int cpu_recomp_ins; - - uint16_t npxs, - npxc; - - double ST[8]; - - uint16_t MM_w4[8]; - - MMX_REG MM[8]; - - uint16_t old_npxc, - new_npxc; - uint32_t last_ea; - - 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 - - x86seg seg_cs, - seg_ds, - seg_es, - seg_ss, - seg_fs, - seg_gs; - - uint16_t flags, eflags; -} cpu_state; - -/*The cpu_state.flags below must match in both cpu_cur_status and block->status for a block - to be valid*/ -#define CPU_STATUS_USE32 (1 << 0) -#define CPU_STATUS_STACK32 (1 << 1) -#define CPU_STATUS_PMODE (1 << 2) -#define CPU_STATUS_V86 (1 << 3) -#define CPU_STATUS_FLAGS 0xffff - -/*If the cpu_state.flags below are set in cpu_cur_status, they must be set in block->status. - Otherwise they are ignored*/ -#define CPU_STATUS_NOTFLATDS (1 << 8) -#define CPU_STATUS_NOTFLATSS (1 << 9) -#define CPU_STATUS_MASK 0xff00 - -#ifdef __MSC__ -# define COMPILE_TIME_ASSERT(expr) /*nada*/ -#else -# ifdef EXTREME_DEBUG -# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0]; -# else -# define COMPILE_TIME_ASSERT(expr) /*nada*/ -# endif -#endif - -COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128) - -#define cpu_state_offset(MEMBER) ((uint8_t)((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)) - -#define EAX cpu_state.regs[0].l -#define AX cpu_state.regs[0].w -#define AL cpu_state.regs[0].b.l -#define AH cpu_state.regs[0].b.h -#define ECX cpu_state.regs[1].l -#define CX cpu_state.regs[1].w -#define CL cpu_state.regs[1].b.l -#define CH cpu_state.regs[1].b.h -#define EDX cpu_state.regs[2].l -#define DX cpu_state.regs[2].w -#define DL cpu_state.regs[2].b.l -#define DH cpu_state.regs[2].b.h -#define EBX cpu_state.regs[3].l -#define BX cpu_state.regs[3].w -#define BL cpu_state.regs[3].b.l -#define BH cpu_state.regs[3].b.h -#define ESP cpu_state.regs[4].l -#define EBP cpu_state.regs[5].l -#define ESI cpu_state.regs[6].l -#define EDI cpu_state.regs[7].l -#define SP cpu_state.regs[4].w -#define BP cpu_state.regs[5].w -#define SI cpu_state.regs[6].w -#define DI cpu_state.regs[7].w - -#define cycles cpu_state._cycles - -#define cpu_rm cpu_state.rm_data.rm_mod_reg.rm -#define cpu_mod cpu_state.rm_data.rm_mod_reg.mod -#define cpu_reg cpu_state.rm_data.rm_mod_reg.reg - -#define CR4_TSD (1 << 2) -#define CR4_DE (1 << 3) -#define CR4_MCE (1 << 6) -#define CR4_PCE (1 << 8) -#define CR4_OSFXSR (1 << 9) - - -/* Global variables. */ -extern int cpu_iscyrix; -extern int cpu_16bitbus; -extern int cpu_busspeed; -extern int cpu_multi; -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 isibmcpu; -extern int is_rapidcad; -extern int hasfpu; -#define CPU_FEATURE_RDTSC (1 << 0) -#define CPU_FEATURE_MSR (1 << 1) -#define CPU_FEATURE_MMX (1 << 2) -#define CPU_FEATURE_CR4 (1 << 3) -#define CPU_FEATURE_VME (1 << 4) -#define CPU_FEATURE_CX8 (1 << 5) -#define CPU_FEATURE_3DNOW (1 << 6) - -extern uint32_t cpu_features; - -extern int in_smm, smi_line, smi_latched; -extern uint32_t smbase; - -extern uint16_t cpu_cur_status; -extern uint64_t cpu_CR4_mask; -extern uint64_t tsc; -extern msr_t msr; -extern uint8_t opcode; -extern int insc; -extern int fpucount; -extern float mips,flops; -extern int clockrate; -extern int cgate16; -extern int cpl_override; -extern int CPUID; -extern uint64_t xt_cpu_multi; -extern int isa_cycles; -extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw; -extern int ins,output; -extern uint32_t pccache; -extern uint8_t *pccache2; - -extern double bus_timing; -extern uint64_t pmc[2]; -extern uint16_t temp_seg_data[4]; -extern uint16_t cs_msr; -extern uint32_t esp_msr; -extern uint32_t eip_msr; - -/* For the AMD K6. */ -extern uint64_t star; - -#define FPU_CW_Reserved_Bits (0xe0c0) - -extern cr0_t CR0; -#define cr0 CR0.l -#define msw CR0.w -extern uint32_t cr2, cr3, cr4; -extern uint32_t dr[8]; - - -/*Segments - - _cs,_ds,_es,_ss are the segment structures - CS,DS,ES,SS is the 16-bit data - cs,ds,es,ss are defines to the bases*/ -extern x86seg gdt,ldt,idt,tr; -extern x86seg _oldds; -#define CS cpu_state.seg_cs.seg -#define DS cpu_state.seg_ds.seg -#define ES cpu_state.seg_es.seg -#define SS cpu_state.seg_ss.seg -#define FS cpu_state.seg_fs.seg -#define GS cpu_state.seg_gs.seg -#define cs cpu_state.seg_cs.base -#define ds cpu_state.seg_ds.base -#define es cpu_state.seg_es.base -#define ss cpu_state.seg_ss.base -#define fs_seg cpu_state.seg_fs.base -#define gs cpu_state.seg_gs.base - - -#define ISA_CYCLES(x) (x * isa_cycles) - -extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l; -extern int cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles; -extern int cpu_waitstates; -extern int cpu_cache_int_enabled, cpu_cache_ext_enabled; -extern int cpu_pci_speed; - -extern int timing_rr; -extern int timing_mr, timing_mrl; -extern int timing_rm, timing_rml; -extern int timing_mm, timing_mml; -extern int timing_bt, timing_bnt; -extern int timing_int, timing_int_rm, timing_int_v86, timing_int_pm; -extern int timing_int_pm_outer, timing_iret_rm, timing_iret_v86, timing_iret_pm; -extern int timing_iret_pm_outer, timing_call_rm, timing_call_pm; -extern int timing_call_pm_gate, timing_call_pm_gate_inner; -extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer; -extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate; -extern int timing_misaligned; - - -extern CPU cpus_pcjr[]; // FIXME: should be in machine file! -extern CPU cpus_europc[]; // FIXME: should be in machine file! -extern CPU cpus_pc1512[]; // FIXME: should be in machine file! -extern CPU cpus_ibmat[]; // FIXME: should be in machine file! -extern CPU cpus_ibmxt286[]; // FIXME: should be in machine file! -extern CPU cpus_ps1_m2011[]; // FIXME: should be in machine file! -extern CPU cpus_ps2_m30_286[]; // FIXME: should be in machine file! -#if 0 -extern CPU cpus_acer[]; // FIXME: should be in machine file! -#endif - - -/* Functions. */ -extern int cpu_has_feature(int feature); - -int loadseg(uint16_t seg, x86seg *s); -void loadseg_dynarec(uint16_t seg, x86seg *s); -void loadcs(uint16_t seg); - -extern char *cpu_current_pc(char *bufp); - -extern void cpu_update_waitstates(void); -extern void cpu_set(void); - -extern void cpu_CPUID(void); -extern void cpu_RDMSR(void); -extern void cpu_WRMSR(void); - -extern int checkio(int port); -extern void codegen_block_end(void); -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 exec386(int cycs); -extern void exec386_dynarec(int cycs); -extern int idivl(int32_t val); -void pmodeint(int num, int soft); -int loadseg(uint16_t seg, x86seg *s); -void loadcs(uint16_t seg); -void loadcscall(uint16_t seg, uint32_t old_pc); -void loadcsjmp(uint16_t seg, uint32_t old_pc); -void pmoderetf(int is32, uint16_t off); -void pmodeiret(int is32); -extern void resetmcr(void); -extern void resetx86(void); -extern void refreshread(void); -extern void resetreadlookup(void); -extern void softresetx86(void); -extern void x86_int(int num); -extern void x86_int_sw(int num); -extern int x86_int_sw_rm(int num); -extern void x86gpf(char *s, uint16_t error); -extern void x86np(char *s, uint16_t error); -extern void x86ss(char *s, uint16_t error); -extern void x86ts(char *s, uint16_t error); - -#ifdef ENABLE_808X_LOG -extern void dumpregs(int __force); -extern void x87_dumpregs(void); -extern void x87_reset(void); -#endif - -extern int cpu_effective, cpu_alt_reset; -extern void cpu_dynamic_switch(int new_cpu); - - -#endif /*EMU_CPU_H*/ diff --git a/src/cpu_new/x86_flags_dynarec.h b/src/cpu_new/x86_flags_dynarec.h deleted file mode 100644 index 2a5212afa..000000000 --- a/src/cpu_new/x86_flags_dynarec.h +++ /dev/null @@ -1,528 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -/* This file is needed so that the dynarec can use the old flags - functions, while the interpreter can use the new ones. */ -extern int tempc; - -enum -{ - FLAGS_UNKNOWN, - - FLAGS_ZN8, - FLAGS_ZN16, - FLAGS_ZN32, - - FLAGS_ADD8, - FLAGS_ADD16, - FLAGS_ADD32, - - FLAGS_SUB8, - FLAGS_SUB16, - FLAGS_SUB32, - - FLAGS_SHL8, - FLAGS_SHL16, - FLAGS_SHL32, - - FLAGS_SHR8, - FLAGS_SHR16, - FLAGS_SHR32, - - FLAGS_SAR8, - FLAGS_SAR16, - FLAGS_SAR32, - - FLAGS_INC8, - FLAGS_INC16, - FLAGS_INC32, - - FLAGS_DEC8, - FLAGS_DEC16, - FLAGS_DEC32 -}; - -static __inline int ZF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - return !cpu_state.flags_res; - - case FLAGS_UNKNOWN: - return cpu_state.flags & Z_FLAG; - - default: - return 0; - } -} - -static __inline int NF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ADD8: - case FLAGS_SUB8: - case FLAGS_SHL8: - case FLAGS_SHR8: - case FLAGS_SAR8: - case FLAGS_INC8: - case FLAGS_DEC8: - return cpu_state.flags_res & 0x80; - - case FLAGS_ZN16: - case FLAGS_ADD16: - case FLAGS_SUB16: - case FLAGS_SHL16: - case FLAGS_SHR16: - case FLAGS_SAR16: - case FLAGS_INC16: - case FLAGS_DEC16: - return cpu_state.flags_res & 0x8000; - - case FLAGS_ZN32: - case FLAGS_ADD32: - case FLAGS_SUB32: - case FLAGS_SHL32: - case FLAGS_SHR32: - case FLAGS_SAR32: - case FLAGS_INC32: - case FLAGS_DEC32: - return cpu_state.flags_res & 0x80000000; - - case FLAGS_UNKNOWN: - return cpu_state.flags & N_FLAG; - - default: - return 0; - } -} - -static __inline int PF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - return znptable8[cpu_state.flags_res & 0xff] & P_FLAG; - - case FLAGS_UNKNOWN: - return cpu_state.flags & P_FLAG; - - default: - return 0; - } -} - -static __inline int VF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - return 0; - - case FLAGS_ADD8: - case FLAGS_INC8: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); - case FLAGS_ADD16: - case FLAGS_INC16: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); - case FLAGS_ADD32: - case FLAGS_INC32: - return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); - - case FLAGS_SUB8: - case FLAGS_DEC8: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80); - case FLAGS_SUB16: - case FLAGS_DEC16: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000); - case FLAGS_SUB32: - case FLAGS_DEC32: - return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000); - - case FLAGS_SHL8: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80); - case FLAGS_SHL16: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x8000); - case FLAGS_SHL32: - return (((cpu_state.flags_op1 << cpu_state.flags_op2) ^ (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1))) & 0x80000000); - - case FLAGS_SHR8: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80)); - case FLAGS_SHR16: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000)); - case FLAGS_SHR32: - return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000)); - - case FLAGS_UNKNOWN: - return cpu_state.flags & V_FLAG; - - default: - return 0; - } -} - -static __inline int AF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - case FLAGS_SHL8: - case FLAGS_SHL16: - case FLAGS_SHL32: - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - case FLAGS_SAR8: - case FLAGS_SAR16: - case FLAGS_SAR32: - return 0; - - case FLAGS_ADD8: - case FLAGS_ADD16: - case FLAGS_ADD32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10; - - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10; - - case FLAGS_UNKNOWN: - return cpu_state.flags & A_FLAG; - - default: - return 0; - } -} - -static __inline int CF_SET_dynarec() -{ - switch (cpu_state.flags_op) - { - case FLAGS_ADD8: - return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100; - case FLAGS_ADD16: - return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000; - case FLAGS_ADD32: - return (cpu_state.flags_res < cpu_state.flags_op1); - - case FLAGS_SUB8: - case FLAGS_SUB16: - case FLAGS_SUB32: - return (cpu_state.flags_op1 < cpu_state.flags_op2); - - case FLAGS_SHL8: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80; - case FLAGS_SHL16: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000; - case FLAGS_SHL32: - return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000; - - case FLAGS_SHR8: - case FLAGS_SHR16: - case FLAGS_SHR32: - return (cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - - case FLAGS_SAR8: - return ((int8_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_SAR16: - return ((int16_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - case FLAGS_SAR32: - return ((int32_t)cpu_state.flags_op1 >> (cpu_state.flags_op2 - 1)) & 1; - - case FLAGS_ZN8: - case FLAGS_ZN16: - case FLAGS_ZN32: - return 0; - - case FLAGS_DEC8: - case FLAGS_DEC16: - case FLAGS_DEC32: - case FLAGS_INC8: - case FLAGS_INC16: - case FLAGS_INC32: - case FLAGS_UNKNOWN: - return cpu_state.flags & C_FLAG; - - default: - return 0; - } -} - -static __inline void flags_rebuild_dynarec() -{ - if (cpu_state.flags_op != FLAGS_UNKNOWN) - { - uint16_t tempf = 0; - if (CF_SET_dynarec()) tempf |= C_FLAG; - if (PF_SET_dynarec()) tempf |= P_FLAG; - if (AF_SET_dynarec()) tempf |= A_FLAG; - if (ZF_SET_dynarec()) tempf |= Z_FLAG; - if (NF_SET_dynarec()) tempf |= N_FLAG; - if (VF_SET_dynarec()) tempf |= V_FLAG; - cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf; - cpu_state.flags_op = FLAGS_UNKNOWN; - } -} - -static __inline void flags_extract_dynarec() -{ - cpu_state.flags_op = FLAGS_UNKNOWN; -} - -static __inline void flags_rebuild_c_dynarec() -{ - if (cpu_state.flags_op != FLAGS_UNKNOWN) - { - if (CF_SET_dynarec()) - cpu_state.flags |= C_FLAG; - else - cpu_state.flags &= ~C_FLAG; - } -} - -static __inline void setznp8_dynarec(uint8_t val) -{ - cpu_state.flags_op = FLAGS_ZN8; - cpu_state.flags_res = val; -} -static __inline void setznp16_dynarec(uint16_t val) -{ - cpu_state.flags_op = FLAGS_ZN16; - cpu_state.flags_res = val; -} -static __inline void setznp32_dynarec(uint32_t val) -{ - cpu_state.flags_op = FLAGS_ZN32; - cpu_state.flags_res = val; -} - -#define set_flags_shift_dynarec(op, orig, shift, res) \ - cpu_state.flags_op = op; \ - cpu_state.flags_res = res; \ - cpu_state.flags_op1 = orig; \ - cpu_state.flags_op2 = shift; - -static __inline void setadd8_dynarec(uint8_t a, uint8_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xff; - cpu_state.flags_op = FLAGS_ADD8; -} -static __inline void setadd16_dynarec(uint16_t a, uint16_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xffff; - cpu_state.flags_op = FLAGS_ADD16; -} -static __inline void setadd32_dynarec(uint32_t a, uint32_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a + b; - cpu_state.flags_op = FLAGS_ADD32; -} -static __inline void setadd8nc_dynarec(uint8_t a, uint8_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xff; - cpu_state.flags_op = FLAGS_INC8; -} -static __inline void setadd16nc_dynarec(uint16_t a, uint16_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a + b) & 0xffff; - cpu_state.flags_op = FLAGS_INC16; -} -static __inline void setadd32nc_dynarec(uint32_t a, uint32_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a + b; - cpu_state.flags_op = FLAGS_INC32; -} - -static __inline void setsub8_dynarec(uint8_t a, uint8_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xff; - cpu_state.flags_op = FLAGS_SUB8; -} -static __inline void setsub16_dynarec(uint16_t a, uint16_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xffff; - cpu_state.flags_op = FLAGS_SUB16; -} -static __inline void setsub32_dynarec(uint32_t a, uint32_t b) -{ - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a - b; - cpu_state.flags_op = FLAGS_SUB32; -} - -static __inline void setsub8nc_dynarec(uint8_t a, uint8_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xff; - cpu_state.flags_op = FLAGS_DEC8; -} -static __inline void setsub16nc_dynarec(uint16_t a, uint16_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = (a - b) & 0xffff; - cpu_state.flags_op = FLAGS_DEC16; -} -static __inline void setsub32nc_dynarec(uint32_t a, uint32_t b) -{ - flags_rebuild_c_dynarec(); - cpu_state.flags_op1 = a; - cpu_state.flags_op2 = b; - cpu_state.flags_res = a - b; - cpu_state.flags_op = FLAGS_DEC32; -} - -static __inline void setadc8_dynarec(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=znptable8[c&0xFF]; - if (c&0x100) cpu_state.flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) cpu_state.flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG; -} -static __inline void setadc16_dynarec(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=znptable16[c&0xFFFF]; - if (c&0x10000) cpu_state.flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) cpu_state.flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) cpu_state.flags|=A_FLAG; -} -static __inline void setadc32_dynarec(uint32_t a, uint32_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - cpu_state.flags_op = FLAGS_UNKNOWN; - cpu_state.flags&=~0x8D5; - cpu_state.flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0)); - cpu_state.flags|=(znptable8[c&0xFF]&P_FLAG); - if ((ca) || (c==a && tempc)) cpu_state.flags|=C_FLAG; - if ((a^b)&(a^c)&0x80000000) cpu_state.flags|=V_FLAG; - if (((a&0xF)-((b&0xF)+tempc))&0x10) cpu_state.flags|=A_FLAG; -} - -extern void cpu_386_flags_extract(); -extern void cpu_386_flags_rebuild(); \ No newline at end of file diff --git a/src/cpu_new/x86_ops_amd.h b/src/cpu_new/x86_ops_amd.h deleted file mode 100644 index 8f003e1fb..000000000 --- a/src/cpu_new/x86_ops_amd.h +++ /dev/null @@ -1,192 +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. - * - * AMD SYSCALL and SYSRET CPU Instructions. - * - * Version: @(#)x86_ops_amd.h 1.0.4 2018/10/17 - * - * Author: Miran Grca, - * 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 */ - -#define AMD_SYSCALL_EIP (star & 0xFFFFFFFF) -#define AMD_SYSCALL_SB ((star >> 32) & 0xFFFF) -#define AMD_SYSRET_SB ((star >> 48) & 0xFFFF) - -/* 0F 05 */ -static int opSYSCALL(uint32_t fetchdat) -{ - uint16_t syscall_cs_seg_data[4] = {0, 0, 0, 0}; - uint16_t syscall_ss_seg_data[4] = {0, 0, 0, 0}; - - if (!(cr0 & 1)) return internal_illegal("SYSCALL: CPU not in protected mode"); - if (!AMD_SYSCALL_SB) return internal_illegal("SYSCALL: AMD SYSCALL SB MSR is zero"); - - /* Set VM, IF, RF to 0. */ - /* cpu_state.eflags &= ~0x00030200; - cpu_state.flags &= ~0x0200; */ - - /* Let's do this by the AMD spec. */ - ECX = cpu_state.pc; - - cpu_state.eflags &= ~0x0002; - cpu_state.flags &= ~0x0200; - - /* CS */ - cpu_state.seg_cs.seg = AMD_SYSCALL_SB & ~7; - if (AMD_SYSCALL_SB & 4) - { - if (cpu_state.seg_cs.seg >= ldt.limit) - { - x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSCALL_SB,ldt.limit); - x86gpf(NULL, AMD_SYSCALL_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg +=ldt.base; - } - else - { - if (cpu_state.seg_cs.seg >= gdt.limit) - { - x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSCALL_SB,gdt.limit); - x86gpf(NULL, AMD_SYSCALL_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg += gdt.base; - } - cpl_override = 1; - - syscall_cs_seg_data[0] = 0xFFFF; - syscall_cs_seg_data[1] = 0; - syscall_cs_seg_data[2] = 0x9B00; - syscall_cs_seg_data[3] = 0xC0; - - cpl_override = 0; - - use32 = 0x300; - CS = (AMD_SYSCALL_SB & ~3) | 0; - - do_seg_load(&cpu_state.seg_cs, syscall_cs_seg_data); - use32 = 0x300; - - CS = (CS & 0xFFFC) | 0; - - cpu_state.seg_cs.limit = 0xFFFFFFFF; - cpu_state.seg_cs.limit_high = 0xFFFFFFFF; - - /* SS */ - syscall_ss_seg_data[0] = 0xFFFF; - syscall_ss_seg_data[1] = 0; - syscall_ss_seg_data[2] = 0x9300; - syscall_ss_seg_data[3] = 0xC0; - do_seg_load(&cpu_state.seg_ss, syscall_ss_seg_data); - cpu_state.seg_ss.seg = (AMD_SYSCALL_SB + 8) & 0xFFFC; - stack32 = 1; - - cpu_state.seg_ss.limit = 0xFFFFFFFF; - cpu_state.seg_ss.limit_high = 0xFFFFFFFF; - - cpu_state.seg_ss.checked = 0; - - cpu_state.pc = AMD_SYSCALL_EIP; - - CLOCK_CYCLES(20); - - CPU_BLOCK_END(); - - return 0; -} - -/* 0F 07 */ -static int opSYSRET(uint32_t fetchdat) -{ - uint16_t sysret_cs_seg_data[4] = {0, 0, 0, 0}; - uint16_t sysret_ss_seg_data[4] = {0, 0, 0, 0}; - - if (!AMD_SYSRET_SB) return internal_illegal("SYSRET: CS MSR is zero"); - if (!(cr0 & 1)) return internal_illegal("SYSRET: CPU not in protected mode"); - - cpu_state.pc = ECX; - - cpu_state.eflags |= (1 << 1); - - /* CS */ - cpu_state.seg_cs.seg = AMD_SYSRET_SB & ~7; - if (AMD_SYSRET_SB & 4) - { - if (cpu_state.seg_cs.seg >= ldt.limit) - { - x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSRET_SB,ldt.limit); - x86gpf(NULL, AMD_SYSRET_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg +=ldt.base; - } - else - { - if (cpu_state.seg_cs.seg >= gdt.limit) - { - x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSRET_SB,gdt.limit); - x86gpf(NULL, AMD_SYSRET_SB & ~3); - return 1; - } - cpu_state.seg_cs.seg += gdt.base; - } - cpl_override = 1; - - sysret_cs_seg_data[0] = 0xFFFF; - sysret_cs_seg_data[1] = 0; - sysret_cs_seg_data[2] = 0xFB00; - sysret_cs_seg_data[3] = 0xC0; - - cpl_override = 0; - - use32 = 0x300; - CS = (AMD_SYSRET_SB & ~3) | 3; - - do_seg_load(&cpu_state.seg_cs, sysret_cs_seg_data); - flushmmucache_cr3(); - use32 = 0x300; - - CS = (CS & 0xFFFC) | 3; - - cpu_state.seg_cs.limit = 0xFFFFFFFF; - cpu_state.seg_cs.limit_high = 0xFFFFFFFF; - - /* SS */ - sysret_ss_seg_data[0] = 0xFFFF; - sysret_ss_seg_data[1] = 0; - sysret_ss_seg_data[2] = 0xF300; - sysret_ss_seg_data[3] = 0xC0; - do_seg_load(&cpu_state.seg_ss, sysret_ss_seg_data); - cpu_state.seg_ss.seg = ((AMD_SYSRET_SB + 8) & 0xFFFC) | 3; - stack32 = 1; - - cpu_state.seg_ss.limit = 0xFFFFFFFF; - cpu_state.seg_ss.limit_high = 0xFFFFFFFF; - - cpu_state.seg_ss.checked = 0; - - CLOCK_CYCLES(20); - - CPU_BLOCK_END(); - - return 0; -} diff --git a/src/cpu_new/x86_ops_bcd.h b/src/cpu_new/x86_ops_bcd.h deleted file mode 100644 index cd29b1405..000000000 --- a/src/cpu_new/x86_ops_bcd.h +++ /dev/null @@ -1,113 +0,0 @@ -static int opAAA(uint32_t fetchdat) -{ - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) - { - AL += 6; - AH++; - cpu_state.flags |= (A_FLAG | C_FLAG); - } - else - cpu_state.flags &= ~(A_FLAG | C_FLAG); - AL &= 0xF; - CLOCK_CYCLES(is486 ? 3 : 4); - PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opAAD(uint32_t fetchdat) -{ - int base = getbytef(); - if (cpu_manufacturer != MANU_INTEL) base = 10; - AL = (AH * base) + AL; - AH = 0; - setznp16(AX); - CLOCK_CYCLES((is486) ? 14 : 19); - PREFETCH_RUN(is486 ? 14 : 19, 2, -1, 0,0,0,0, 0); - return 0; -} - -static int opAAM(uint32_t fetchdat) -{ - int base = getbytef(); - if (!base || cpu_manufacturer != MANU_INTEL) base = 10; - AH = AL / base; - AL %= base; - setznp16(AX); - CLOCK_CYCLES((is486) ? 15 : 17); - PREFETCH_RUN(is486 ? 15 : 17, 2, -1, 0,0,0,0, 0); - return 0; -} - -static int opAAS(uint32_t fetchdat) -{ - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9)) - { - AL -= 6; - AH--; - cpu_state.flags |= (A_FLAG | C_FLAG); - } - else - cpu_state.flags &= ~(A_FLAG | C_FLAG); - AL &= 0xF; - CLOCK_CYCLES(is486 ? 3 : 4); - PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opDAA(uint32_t fetchdat) -{ - uint16_t tempw; - - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) - { - int tempi = ((uint16_t)AL) + 6; - AL += 6; - cpu_state.flags |= A_FLAG; - if (tempi & 0x100) cpu_state.flags |= C_FLAG; - } - if ((cpu_state.flags & C_FLAG) || (AL > 0x9f)) - { - AL += 0x60; - cpu_state.flags |= C_FLAG; - } - - tempw = cpu_state.flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags_rebuild(); - cpu_state.flags |= tempw; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); - - return 0; -} - -static int opDAS(uint32_t fetchdat) -{ - uint16_t tempw; - - flags_rebuild(); - if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) - { - int tempi = ((uint16_t)AL) - 6; - AL -= 6; - cpu_state.flags |= A_FLAG; - if (tempi & 0x100) cpu_state.flags |= C_FLAG; - } - if ((cpu_state.flags & C_FLAG) || (AL > 0x9f)) - { - AL -= 0x60; - cpu_state.flags |= C_FLAG; - } - - tempw = cpu_state.flags & (C_FLAG | A_FLAG); - setznp8(AL); - flags_rebuild(); - cpu_state.flags |= tempw; - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0); - - return 0; -} diff --git a/src/cpu_new/x86_ops_bitscan.h b/src/cpu_new/x86_ops_bitscan.h deleted file mode 100644 index 01d9c5795..000000000 --- a/src/cpu_new/x86_ops_bitscan.h +++ /dev/null @@ -1,159 +0,0 @@ -#define BS_common(start, end, dir, dest, time) \ - flags_rebuild(); \ - instr_cycles = 0; \ - if (temp) \ - { \ - int c; \ - cpu_state.flags &= ~Z_FLAG; \ - for (c = start; c != end; c += dir) \ - { \ - CLOCK_CYCLES(time); \ - instr_cycles += time; \ - if (temp & (1 << c)) \ - { \ - dest = c; \ - break; \ - } \ - } \ - } \ - else \ - cpu_state.flags |= Z_FLAG; - -static int opBSF_w_a16(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opBSF_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opBSF_l_a16(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return 0; -} -static int opBSF_l_a32(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return 0; -} - -static int opBSR_w_a16(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opBSR_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - - BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opBSR_l_a16(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return 0; -} -static int opBSR_l_a32(uint32_t fetchdat) -{ - uint32_t temp; - int instr_cycles = 0; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteal(); if (cpu_state.abrt) return 1; - - BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3); - - CLOCK_CYCLES((is486) ? 6 : 10); - instr_cycles += ((is486) ? 6 : 10); - PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return 0; -} - diff --git a/src/cpu_new/x86_ops_flag.h b/src/cpu_new/x86_ops_flag.h deleted file mode 100644 index d21408c8b..000000000 --- a/src/cpu_new/x86_ops_flag.h +++ /dev/null @@ -1,275 +0,0 @@ -static int opCMC(uint32_t fetchdat) -{ - flags_rebuild(); - cpu_state.flags ^= C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} - - -static int opCLC(uint32_t fetchdat) -{ - flags_rebuild(); - cpu_state.flags &= ~C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opCLD(uint32_t fetchdat) -{ - cpu_state.flags &= ~D_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opCLI(uint32_t fetchdat) -{ - if (!IOPLp) - { - if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) - { - cpu_state.eflags &= ~VIF_FLAG; - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - cpu_state.flags &= ~I_FLAG; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opSTC(uint32_t fetchdat) -{ - flags_rebuild(); - cpu_state.flags |= C_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opSTD(uint32_t fetchdat) -{ - cpu_state.flags |= D_FLAG; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opSTI(uint32_t fetchdat) -{ - if (!IOPLp) - { - if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || - ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) - { - if (cpu_state.eflags & VIP_FLAG) - { - x86gpf(NULL,0); - return 1; - } - else - cpu_state.eflags |= VIF_FLAG; - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - cpu_state.flags |= I_FLAG; - - CPU_BLOCK_END(); - - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opSAHF(uint32_t fetchdat) -{ - flags_rebuild(); - cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - - codegen_flags_changed = 0; - - return 0; -} -static int opLAHF(uint32_t fetchdat) -{ - flags_rebuild(); - AH = cpu_state.flags & 0xff; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opPUSHF(uint32_t fetchdat) -{ - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - if (cr4 & CR4_VME) - { - uint16_t temp; - - flags_rebuild(); - temp = (cpu_state.flags & ~I_FLAG) | 0x3000; - if (cpu_state.eflags & VIF_FLAG) - temp |= I_FLAG; - PUSH_W(temp); - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - { - flags_rebuild(); - PUSH_W(cpu_state.flags); - } - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opPUSHFD(uint32_t fetchdat) -{ - uint16_t tempw; - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - x86gpf(NULL, 0); - return 1; - } - if (cpu_CR4_mask & CR4_VME) tempw = cpu_state.eflags & 0x3c; - else if (CPUID) tempw = cpu_state.eflags & 0x24; - else tempw = cpu_state.eflags & 4; - flags_rebuild(); - PUSH_L(cpu_state.flags | (tempw << 16)); - CLOCK_CYCLES(4); - PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0); - return cpu_state.abrt; -} - -static int opPOPF_286(uint32_t fetchdat) -{ - uint16_t tempw; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - x86gpf(NULL, 0); - return 1; - } - - tempw = POP_W(); if (cpu_state.abrt) return 1; - - if (!(msw & 1)) cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2; - else if (!(CPL)) cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - flags_extract(); - - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - - codegen_flags_changed = 0; - - return 0; -} -static int opPOPF(uint32_t fetchdat) -{ - uint16_t tempw; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - if (cr4 & CR4_VME) - { - uint32_t old_esp = ESP; - - tempw = POP_W(); - if (cpu_state.abrt) - { - ESP = old_esp; - return 1; - } - - if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) - { - ESP = old_esp; - x86gpf(NULL, 0); - return 1; - } - if (tempw & I_FLAG) - cpu_state.eflags |= VIF_FLAG; - else - cpu_state.eflags &= ~VIF_FLAG; - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - } - else - { - x86gpf(NULL, 0); - return 1; - } - } - else - { - tempw = POP_W(); - if (cpu_state.abrt) - return 1; - - if (!(CPL) || !(msw & 1)) - cpu_state.flags = (tempw & 0x7fd5) | 2; - else if (IOPLp) - cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2; - else - cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2; - } - flags_extract(); - - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - - codegen_flags_changed = 0; - - return 0; -} -static int opPOPFD(uint32_t fetchdat) -{ - uint32_t templ; - - if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) - { - x86gpf(NULL, 0); - return 1; - } - - templ = POP_L(); if (cpu_state.abrt) return 1; - - if (!(CPL) || !(msw & 1)) cpu_state.flags = (templ & 0x7fd5) | 2; - else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2; - else cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2; - - templ &= is486 ? 0x3c0000 : 0; - templ |= ((cpu_state.eflags&3) << 16); - if (cpu_CR4_mask & CR4_VME) cpu_state.eflags = (templ >> 16) & 0x3f; - else if (CPUID) cpu_state.eflags = (templ >> 16) & 0x27; - else if (is486) cpu_state.eflags = (templ >> 16) & 7; - else cpu_state.eflags = (templ >> 16) & 3; - - flags_extract(); - - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0); - - codegen_flags_changed = 0; - - return 0; -} diff --git a/src/cpu_new/x86_ops_fpu.h b/src/cpu_new/x86_ops_fpu.h deleted file mode 100644 index 8c264374f..000000000 --- a/src/cpu_new/x86_ops_fpu.h +++ /dev/null @@ -1,82 +0,0 @@ -static int opESCAPE_d8_a16(uint32_t fetchdat) -{ - return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat); -} -static int opESCAPE_d8_a32(uint32_t fetchdat) -{ - return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat); -} - -static int opESCAPE_d9_a16(uint32_t fetchdat) -{ - return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_d9_a32(uint32_t fetchdat) -{ - return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat); -} - -static int opESCAPE_da_a16(uint32_t fetchdat) -{ - return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_da_a32(uint32_t fetchdat) -{ - return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat); -} - -static int opESCAPE_db_a16(uint32_t fetchdat) -{ - return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_db_a32(uint32_t fetchdat) -{ - return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat); -} - -static int opESCAPE_dc_a16(uint32_t fetchdat) -{ - return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat); -} -static int opESCAPE_dc_a32(uint32_t fetchdat) -{ - return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat); -} - -static int opESCAPE_dd_a16(uint32_t fetchdat) -{ - return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_dd_a32(uint32_t fetchdat) -{ - return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat); -} - -static int opESCAPE_de_a16(uint32_t fetchdat) -{ - return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_de_a32(uint32_t fetchdat) -{ - return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat); -} - -static int opESCAPE_df_a16(uint32_t fetchdat) -{ - return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat); -} -static int opESCAPE_df_a32(uint32_t fetchdat) -{ - return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat); -} - -static int opWAIT(uint32_t fetchdat) -{ - if ((cr0 & 0xa) == 0xa) - { - x86_int(7); - return 1; - } - CLOCK_CYCLES(4); - return 0; -} diff --git a/src/cpu_new/x86_ops_inc_dec.h b/src/cpu_new/x86_ops_inc_dec.h deleted file mode 100644 index d14bae863..000000000 --- a/src/cpu_new/x86_ops_inc_dec.h +++ /dev/null @@ -1,93 +0,0 @@ -#define INC_DEC_OP(name, reg, inc, setflags) \ - static int op ## name (uint32_t fetchdat) \ - { \ - setflags(reg, 1); \ - reg += inc; \ - CLOCK_CYCLES(timing_rr); \ - PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); \ - return 0; \ - } - -INC_DEC_OP(INC_AX, AX, 1, setadd16nc) -INC_DEC_OP(INC_BX, BX, 1, setadd16nc) -INC_DEC_OP(INC_CX, CX, 1, setadd16nc) -INC_DEC_OP(INC_DX, DX, 1, setadd16nc) -INC_DEC_OP(INC_SI, SI, 1, setadd16nc) -INC_DEC_OP(INC_DI, DI, 1, setadd16nc) -INC_DEC_OP(INC_BP, BP, 1, setadd16nc) -INC_DEC_OP(INC_SP, SP, 1, setadd16nc) - -INC_DEC_OP(INC_EAX, EAX, 1, setadd32nc) -INC_DEC_OP(INC_EBX, EBX, 1, setadd32nc) -INC_DEC_OP(INC_ECX, ECX, 1, setadd32nc) -INC_DEC_OP(INC_EDX, EDX, 1, setadd32nc) -INC_DEC_OP(INC_ESI, ESI, 1, setadd32nc) -INC_DEC_OP(INC_EDI, EDI, 1, setadd32nc) -INC_DEC_OP(INC_EBP, EBP, 1, setadd32nc) -INC_DEC_OP(INC_ESP, ESP, 1, setadd32nc) - -INC_DEC_OP(DEC_AX, AX, -1, setsub16nc) -INC_DEC_OP(DEC_BX, BX, -1, setsub16nc) -INC_DEC_OP(DEC_CX, CX, -1, setsub16nc) -INC_DEC_OP(DEC_DX, DX, -1, setsub16nc) -INC_DEC_OP(DEC_SI, SI, -1, setsub16nc) -INC_DEC_OP(DEC_DI, DI, -1, setsub16nc) -INC_DEC_OP(DEC_BP, BP, -1, setsub16nc) -INC_DEC_OP(DEC_SP, SP, -1, setsub16nc) - -INC_DEC_OP(DEC_EAX, EAX, -1, setsub32nc) -INC_DEC_OP(DEC_EBX, EBX, -1, setsub32nc) -INC_DEC_OP(DEC_ECX, ECX, -1, setsub32nc) -INC_DEC_OP(DEC_EDX, EDX, -1, setsub32nc) -INC_DEC_OP(DEC_ESI, ESI, -1, setsub32nc) -INC_DEC_OP(DEC_EDI, EDI, -1, setsub32nc) -INC_DEC_OP(DEC_EBP, EBP, -1, setsub32nc) -INC_DEC_OP(DEC_ESP, ESP, -1, setsub32nc) - - -static int opINCDEC_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; - - if (rmdat&0x38) - { - seteab(temp - 1); if (cpu_state.abrt) return 1; - setsub8nc(temp, 1); - } - else - { - seteab(temp + 1); if (cpu_state.abrt) return 1; - setadd8nc(temp, 1); - } - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - return 0; -} -static int opINCDEC_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; - - if (rmdat&0x38) - { - seteab(temp - 1); if (cpu_state.abrt) return 1; - setsub8nc(temp, 1); - } - else - { - seteab(temp + 1); if (cpu_state.abrt) return 1; - setadd8nc(temp, 1); - } - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - return 0; -} diff --git a/src/cpu_new/x86_ops_int.h b/src/cpu_new/x86_ops_int.h deleted file mode 100644 index 260fcdad5..000000000 --- a/src/cpu_new/x86_ops_int.h +++ /dev/null @@ -1,91 +0,0 @@ -static int opINT3(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - x86_int_sw(3); - CLOCK_CYCLES((is486) ? 44 : 59); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); - return 1; -} - -static int opINT1(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - x86_int_sw(1); - CLOCK_CYCLES((is486) ? 44 : 59); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); - return 1; -} - -static int opINT(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - uint8_t temp = getbytef(); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - if (cr4 & CR4_VME) - { - uint16_t t; - uint8_t d; - - cpl_override = 1; - t = readmemw(tr.base, 0x66) - 32; - cpl_override = 0; - if (cpu_state.abrt) return 1; - - t += (temp >> 3); - if (t <= tr.limit) - { - cpl_override = 1; - d = readmemb(tr.base, t);// + (temp >> 3)); - cpl_override = 0; - if (cpu_state.abrt) return 1; - - if (!(d & (1 << (temp & 7)))) - { - x86_int_sw_rm(temp); - PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0); - return 1; - } - } - } - x86gpf(NULL,0); - return 1; - } - - x86_int_sw(temp); - PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0); - return 1; -} - -static int opINTO(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - if (VF_SET()) - { - cpu_state.oldpc = cpu_state.pc; - x86_int_sw(4); - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); - return 1; - } - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} - diff --git a/src/cpu_new/x86_ops_io.h b/src/cpu_new/x86_ops_io.h deleted file mode 100644 index 9fa91a215..000000000 --- a/src/cpu_new/x86_ops_io.h +++ /dev/null @@ -1,146 +0,0 @@ -static int opIN_AL_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - AL = inb(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_AX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - AX = inw(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_EAX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); - EAX = inl(port); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} - -static int opOUT_AL_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - outb(port, AL); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); - if (port == 0x64) - return x86_was_reset; - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opOUT_AX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - outw(port, AX); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opOUT_EAX_imm(uint32_t fetchdat) -{ - uint16_t port = (uint16_t)getbytef(); - check_io_perm(port); - check_io_perm(port + 1); - check_io_perm(port + 2); - check_io_perm(port + 3); - outl(port, EAX); - CLOCK_CYCLES(10); - PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} - -static int opIN_AL_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - AL = inb(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_AX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - AX = inw(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opIN_EAX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - EAX = inl(DX); - CLOCK_CYCLES(12); - PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} - -static int opOUT_AL_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - outb(DX, AL); - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return x86_was_reset; -} -static int opOUT_AX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - outw(DX, AX); - CLOCK_CYCLES(11); - PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} -static int opOUT_EAX_DX(uint32_t fetchdat) -{ - check_io_perm(DX); - check_io_perm(DX + 1); - check_io_perm(DX + 2); - check_io_perm(DX + 3); - outl(DX, EAX); - PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0); - if (nmi && nmi_enable && nmi_mask) - return 1; - return 0; -} diff --git a/src/cpu_new/x86_ops_misc.h b/src/cpu_new/x86_ops_misc.h deleted file mode 100644 index f8db6c592..000000000 --- a/src/cpu_new/x86_ops_misc.h +++ /dev/null @@ -1,971 +0,0 @@ -static int opCBW(uint32_t fetchdat) -{ - AH = (AL & 0x80) ? 0xff : 0; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opCWDE(uint32_t fetchdat) -{ - EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX; - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opCWD(uint32_t fetchdat) -{ - DX = (AX & 0x8000) ? 0xFFFF : 0; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} -static int opCDQ(uint32_t fetchdat) -{ - EDX = (EAX & 0x80000000) ? 0xffffffff : 0; - CLOCK_CYCLES(2); - PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opNOP(uint32_t fetchdat) -{ - CLOCK_CYCLES((is486) ? 1 : 3); - PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opSETALC(uint32_t fetchdat) -{ - AL = (CF_SET()) ? 0xff : 0; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); - return 0; -} - - - -static int opF6_a16(uint32_t fetchdat) -{ - int tempws, tempws2 = 0; - uint16_t tempw, src16; - uint8_t src, dst; - int8_t temps; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) { - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - } - dst = geteab(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - setznp8(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x10: /*NOT b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x18: /*NEG b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(0 - dst); if (cpu_state.abrt) return 1; - setsub8(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x20: /*MUL AL,b*/ - AX = AL * dst; - flags_rebuild(); - if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(13); - PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x28: /*IMUL AL,b*/ - tempws = (int)((int8_t)AL) * (int)((int8_t)dst); - AX = tempws & 0xffff; - flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x30: /*DIV AL,b*/ - src16 = AX; - if (dst) tempw = src16 / dst; - if (dst && !(tempw & 0xff00)) - { - AH = src16 % dst; - AL = (src16 / dst) &0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x38: /*IDIV AL,b*/ - tempws = (int)(int16_t)AX; - if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); - temps = tempws2 & 0xff; - if (dst && ((int)temps == tempws2)) - { - AH = (tempws % (int)((int8_t)dst)) & 0xff; - AL = tempws2 & 0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags|=0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(19); - PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - - default: - x86illegal(); - } - return 0; -} -static int opF6_a32(uint32_t fetchdat) -{ - int tempws, tempws2 = 0; - uint16_t tempw, src16; - uint8_t src, dst; - int8_t temps; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteab(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - setznp8(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x10: /*NOT b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x18: /*NEG b*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(0 - dst); if (cpu_state.abrt) return 1; - setsub8(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x20: /*MUL AL,b*/ - AX = AL * dst; - flags_rebuild(); - if (AH) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(13); - PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x28: /*IMUL AL,b*/ - tempws = (int)((int8_t)AL) * (int)((int8_t)dst); - AX = tempws & 0xffff; - flags_rebuild(); - if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(14); - PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x30: /*DIV AL,b*/ - src16 = AX; - if (dst) tempw = src16 / dst; - if (dst && !(tempw & 0xff00)) - { - AH = src16 % dst; - AL = (src16 / dst) &0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x38: /*IDIV AL,b*/ - tempws = (int)(int16_t)AX; - if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); - temps = tempws2 & 0xff; - if (dst && ((int)temps == tempws2)) - { - AH = (tempws % (int)((int8_t)dst)) & 0xff; - AL = tempws2 & 0xff; - if (!cpu_iscyrix) - { - flags_rebuild(); - cpu_state.flags |= 0x8D5; /*Not a Cyrix*/ - cpu_state.flags &= ~1; - } - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(19); - PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - - - -static int opF7_w_a16(uint32_t fetchdat) -{ - uint32_t templ, templ2; - int tempws, tempws2 = 0; - int16_t temps16; - uint16_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - src = getword(); if (cpu_state.abrt) return 1; - setznp16(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x10: /*NOT w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x18: /*NEG w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(0 - dst); if (cpu_state.abrt) return 1; - setsub16(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0); - break; - case 0x20: /*MUL AX,w*/ - templ = AX * dst; - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x28: /*IMUL AX,w*/ - templ = (int)((int16_t)AX) * (int)((int16_t)dst); - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(22); - PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x30: /*DIV AX,w*/ - templ = (DX << 16) | AX; - if (dst) templ2 = templ / dst; - if (dst && !(templ2 & 0xffff0000)) - { - DX = templ % dst; - AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - case 0x38: /*IDIV AX,w*/ - tempws = (int)((DX << 16)|AX); - if (dst) tempws2 = tempws / (int)((int16_t)dst); - temps16 = tempws2 & 0xffff; - if ((dst != 0) && ((int)temps16 == tempws2)) - { - DX = tempws % (int)((int16_t)dst); - AX = tempws2 & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(27); - PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - break; - - default: - x86illegal(); - } - return 0; -} -static int opF7_w_a32(uint32_t fetchdat) -{ - uint32_t templ, templ2; - int tempws, tempws2 = 1; - int16_t temps16; - uint16_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteaw(); if (cpu_state.abrt) return 1; - switch (rmdat & 0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - src = getword(); if (cpu_state.abrt) return 1; - setznp16(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x10: /*NOT w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x18: /*NEG w*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(0 - dst); if (cpu_state.abrt) return 1; - setsub16(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1); - break; - case 0x20: /*MUL AX,w*/ - templ = AX * dst; - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (DX) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x28: /*IMUL AX,w*/ - templ = (int)((int16_t)AX) * (int)((int16_t)dst); - AX = templ & 0xFFFF; - DX = templ >> 16; - flags_rebuild(); - if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(22); - PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x30: /*DIV AX,w*/ - templ = (DX << 16) | AX; - if (dst) templ2 = templ / dst; - if (dst && !(templ2 & 0xffff0000)) - { - DX = templ % dst; - AX = (templ / dst) & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { -// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins); - x86_int(0); - return 1; - } - CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22); - PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - case 0x38: /*IDIV AX,w*/ - tempws = (int)((DX << 16)|AX); - if (dst) tempws2 = tempws / (int)((int16_t)dst); - temps16 = tempws2 & 0xffff; - if ((dst != 0) && ((int)temps16 == tempws2)) - { - DX = tempws % (int)((int16_t)dst); - AX = tempws2 & 0xffff; - if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ - } - else - { - x86_int(0); - return 1; - } - CLOCK_CYCLES(27); - PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - -static int opF7_l_a16(uint32_t fetchdat) -{ - uint64_t temp64; - uint32_t src, dst; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*TEST l*/ - case 0x08: - src = getlong(); if (cpu_state.abrt) return 1; - setznp32(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x10: /*NOT l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x18: /*NEG l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(0 - dst); if (cpu_state.abrt) return 1; - setsub32(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0); - break; - case 0x20: /*MUL EAX,l*/ - temp64 = (uint64_t)EAX * (uint64_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); - else cpu_state.flags &= ~(C_FLAG|V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x28: /*IMUL EAX,l*/ - temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(38); - PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x30: /*DIV EAX,l*/ - if (divl(dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES((is486) ? 40 : 38); - PREFETCH_RUN(is486 ? 40:38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - case 0x38: /*IDIV EAX,l*/ - if (idivl((int32_t)dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES(43); - PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - break; - - default: - x86illegal(); - } - return 0; -} -static int opF7_l_a32(uint32_t fetchdat) -{ - uint64_t temp64; - uint32_t src, dst; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - dst = geteal(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*TEST l*/ - case 0x08: - src = getlong(); if (cpu_state.abrt) return 1; - setznp32(src & dst); - if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); - else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x10: /*NOT l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(~dst); if (cpu_state.abrt) return 1; - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x18: /*NEG l*/ - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(0 - dst); if (cpu_state.abrt) return 1; - setsub32(0, dst); - CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml); - PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1); - break; - case 0x20: /*MUL EAX,l*/ - temp64 = (uint64_t)EAX * (uint64_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG); - else cpu_state.flags &= ~(C_FLAG|V_FLAG); - CLOCK_CYCLES(21); - PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x28: /*IMUL EAX,l*/ - temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst; - EAX = temp64 & 0xffffffff; - EDX = temp64 >> 32; - flags_rebuild(); - if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG); - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - CLOCK_CYCLES(38); - PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x30: /*DIV EAX,l*/ - if (divl(dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES((is486) ? 40 : 38); - PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - case 0x38: /*IDIV EAX,l*/ - if (idivl((int32_t)dst)) - return 1; - if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/ - CLOCK_CYCLES(43); - PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - break; - - default: - x86illegal(); - } - return 0; -} - - -static int opHLT(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - if (!((cpu_state.flags & I_FLAG) && pic_intpending)) - { - CLOCK_CYCLES_ALWAYS(100); - cpu_state.pc--; - } - else - CLOCK_CYCLES(5); - - CPU_BLOCK_END(); - PREFETCH_RUN(100, 1, -1, 0,0,0,0, 0); - - return 0; -} - - -static int opLOCK(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 0; - cpu_state.pc++; - - ILLEGAL_ON((fetchdat & 0xff) == 0x90); - - CLOCK_CYCLES(4); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} - - - -static int opBOUND_w_a16(uint32_t fetchdat) -{ - int16_t low, high; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteaw(); - high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - - if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 0); - return 0; -} -static int opBOUND_w_a32(uint32_t fetchdat) -{ - int16_t low, high; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteaw(); - high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - - if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 1); - return 0; -} - -static int opBOUND_l_a16(uint32_t fetchdat) -{ - int32_t low, high; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteal(); - high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - - if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 0); - return 0; -} -static int opBOUND_l_a32(uint32_t fetchdat) -{ - int32_t low, high; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - low = geteal(); - high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - - if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high)) - { - x86_int(5); - return 1; - } - - CLOCK_CYCLES(is486 ? 7 : 10); - PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 1); - return 0; -} - - -static int opCLTS(uint32_t fetchdat) -{ - if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - cr0 &= ~8; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 0,0,0,0, 0); - return 0; -} - -static int opINVD(uint32_t fetchdat) -{ - if (!is486) - { - x86illegal(); - return 1; - } - CLOCK_CYCLES(1000); - CPU_BLOCK_END(); - return 0; -} -static int opWBINVD(uint32_t fetchdat) -{ - if (!is486) - { - x86illegal(); - return 1; - } - CLOCK_CYCLES(10000); - CPU_BLOCK_END(); - return 0; -} - -static int opLOADALL(uint32_t fetchdat) -{ - if (CPL && (cr0&1)) - { - x86gpf(NULL,0); - return 1; - } - msw = (msw & 1) | readmemw(0, 0x806); - cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2; - flags_extract(); - tr.seg = readmemw(0, 0x816); - cpu_state.pc = readmemw(0, 0x81A); - ldt.seg = readmemw(0, 0x81C); - DS = readmemw(0, 0x81E); - SS = readmemw(0, 0x820); - CS = readmemw(0, 0x822); - ES = readmemw(0, 0x824); - DI = readmemw(0, 0x826); - SI = readmemw(0, 0x828); - BP = readmemw(0, 0x82A); - SP = readmemw(0, 0x82C); - BX = readmemw(0, 0x82E); - DX = readmemw(0, 0x830); - CX = readmemw(0, 0x832); - AX = readmemw(0, 0x834); - es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16); - cpu_state.seg_es.access = readmemb(0, 0x839); - cpu_state.seg_es.limit = readmemw(0, 0x83A); - cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16); - cpu_state.seg_cs.access = readmemb(0, 0x83F); - cpu_state.seg_cs.limit = readmemw(0, 0x840); - ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16); - cpu_state.seg_ss.access = readmemb(0, 0x845); - cpu_state.seg_ss.limit = readmemw(0, 0x846); - if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16); - cpu_state.seg_ds.access = readmemb(0, 0x84B); - cpu_state.seg_ds.limit = readmemw(0, 0x84C); - if (cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; - gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16); - gdt.limit = readmemw(0, 0x852); - ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16); - ldt.access = readmemb(0, 0x857); - ldt.limit = readmemw(0, 0x858); - idt.base = readmemw(0, 0x85A) | (readmemb(0, 0x85C) << 16); - idt.limit = readmemw(0, 0x85E); - tr.base = readmemw(0, 0x860) | (readmemb(0, 0x862) << 16); - tr.access = readmemb(0, 0x863); - tr.limit = readmemw(0, 0x864); - CLOCK_CYCLES(195); - PREFETCH_RUN(195, 1, -1, 51,0,0,0, 0); - return 0; -} - -static void set_segment_limit(x86seg *s, uint8_t segdat3) -{ - if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) /*expand-down*/ - { - s->limit_high = s->limit; - s->limit_low = 0; - } - else - { - s->limit_high = (segdat3 & 0x40) ? 0xffffffff : 0xffff; - s->limit_low = s->limit + 1; - } -} - -static void loadall_load_segment(uint32_t addr, x86seg *s) -{ - uint32_t attrib = readmeml(0, addr); - uint32_t segdat3 = (attrib >> 16) & 0xff; - s->access = (attrib >> 8) & 0xff; - s->base = readmeml(0, addr + 4); - s->limit = readmeml(0, addr + 8); - - if (s == &cpu_state.seg_cs) - use32 = (segdat3 & 0x40) ? 0x300 : 0; - if (s == &cpu_state.seg_ss) - stack32 = (segdat3 & 0x40) ? 1 : 0; - - cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32); - if (use32) - cpu_cur_status |= CPU_STATUS_USE32; - if (stack32) - cpu_cur_status |= CPU_STATUS_STACK32; - - set_segment_limit(s, segdat3); - - if (s == &cpu_state.seg_ds) - { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATDS; - } - if (s == &cpu_state.seg_ss) - { - if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff) - cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; - else - cpu_cur_status |= CPU_STATUS_NOTFLATSS; - } -} - -static int opLOADALL386(uint32_t fetchdat) -{ - uint32_t la_addr = es + EDI; - - cr0 = readmeml(0, la_addr); - cpu_state.flags = readmemw(0, la_addr + 4); - cpu_state.eflags = readmemw(0, la_addr + 6); - flags_extract(); - cpu_state.pc = readmeml(0, la_addr + 8); - EDI = readmeml(0, la_addr + 0xC); - ESI = readmeml(0, la_addr + 0x10); - EBP = readmeml(0, la_addr + 0x14); - ESP = readmeml(0, la_addr + 0x18); - EBX = readmeml(0, la_addr + 0x1C); - EDX = readmeml(0, la_addr + 0x20); - ECX = readmeml(0, la_addr + 0x24); - EAX = readmeml(0, la_addr + 0x28); - dr[6] = readmeml(0, la_addr + 0x2C); - dr[7] = readmeml(0, la_addr + 0x30); - tr.seg = readmemw(0, la_addr + 0x34); - ldt.seg = readmemw(0, la_addr + 0x38); - GS = readmemw(0, la_addr + 0x3C); - FS = readmemw(0, la_addr + 0x40); - DS = readmemw(0, la_addr + 0x44); - SS = readmemw(0, la_addr + 0x48); - CS = readmemw(0, la_addr + 0x4C); - ES = readmemw(0, la_addr + 0x50); - - loadall_load_segment(la_addr + 0x54, &tr); - loadall_load_segment(la_addr + 0x60, &idt); - loadall_load_segment(la_addr + 0x6c, &gdt); - loadall_load_segment(la_addr + 0x78, &ldt); - loadall_load_segment(la_addr + 0x84, &cpu_state.seg_gs); - loadall_load_segment(la_addr + 0x90, &cpu_state.seg_fs); - loadall_load_segment(la_addr + 0x9c, &cpu_state.seg_ds); - loadall_load_segment(la_addr + 0xa8, &cpu_state.seg_ss); - loadall_load_segment(la_addr + 0xb4, &cpu_state.seg_cs); - loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es); - - if (CPL==3 && oldcpl!=3) flushmmucache_cr3(); - oldcpl = CPL; - - CLOCK_CYCLES(350); - return 0; -} - -static int opCPUID(uint32_t fetchdat) -{ - if (CPUID) - { - cpu_CPUID(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opRDMSR(uint32_t fetchdat) -{ - if (cpu_has_feature(CPU_FEATURE_MSR)) - { - cpu_RDMSR(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opWRMSR(uint32_t fetchdat) -{ - if (cpu_has_feature(CPU_FEATURE_MSR)) - { - cpu_WRMSR(); - CLOCK_CYCLES(9); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} - -static int opRSM(uint32_t fetchdat) -{ - if(!in_smm) - { - leave_smm(); - if(smi_latched) enter_smm(); - return 0; - } - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; -} \ No newline at end of file diff --git a/src/cpu_new/x86_ops_mmx_cmp.h b/src/cpu_new/x86_ops_mmx_cmp.h deleted file mode 100644 index 0fee95923..000000000 --- a/src/cpu_new/x86_ops_mmx_cmp.h +++ /dev/null @@ -1,205 +0,0 @@ -static int opPCMPEQB_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[0] == src.b[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0; - - return 0; -} -static int opPCMPEQB_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[0] == src.b[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0; - - return 0; -} - -static int opPCMPGTB_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].sb[0] > src.sb[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0; - - return 0; -} -static int opPCMPGTB_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].sb[0] > src.sb[0]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0; - cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0; - - return 0; -} - -static int opPCMPEQW_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[0] == src.w[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0; - - return 0; -} -static int opPCMPEQW_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[0] == src.w[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0; - - return 0; -} - -static int opPCMPGTW_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].sw[0] > src.sw[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0; - - return 0; -} -static int opPCMPGTW_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].sw[0] > src.sw[0]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0; - cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0; - - return 0; -} - -static int opPCMPEQD_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[0] == src.l[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0; - - return 0; -} -static int opPCMPEQD_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[0] == src.l[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0; - - return 0; -} - -static int opPCMPGTD_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].sl[0] > src.sl[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0; - - return 0; -} -static int opPCMPGTD_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].sl[0] > src.sl[0]) ? 0xffffffff : 0; - cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0; - - return 0; -} diff --git a/src/cpu_new/x86_ops_mmx_logic.h b/src/cpu_new/x86_ops_mmx_logic.h deleted file mode 100644 index be5132e85..000000000 --- a/src/cpu_new/x86_ops_mmx_logic.h +++ /dev/null @@ -1,91 +0,0 @@ -static int opPAND_a16(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q &= src.q; - return 0; -} -static int opPAND_a32(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q &= src.q; - return 0; -} - -static int opPANDN_a16(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; - return 0; -} -static int opPANDN_a32(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q; - return 0; -} - -static int opPOR_a16(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q |= src.q; - return 0; -} -static int opPOR_a32(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q |= src.q; - return 0; -} - -static int opPXOR_a16(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_16(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q ^= src.q; - return 0; -} -static int opPXOR_a32(uint32_t fetchdat) -{ - MMX_REG src; - MMX_ENTER(); - - fetch_ea_32(fetchdat); - MMX_GETSRC(); - - cpu_state.MM[cpu_reg].q ^= src.q; - return 0; -} diff --git a/src/cpu_new/x86_ops_mov.h b/src/cpu_new/x86_ops_mov.h deleted file mode 100644 index 2c96317b7..000000000 --- a/src/cpu_new/x86_ops_mov.h +++ /dev/null @@ -1,784 +0,0 @@ -static int opMOV_AL_imm(uint32_t fetchdat) -{ - AL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_AH_imm(uint32_t fetchdat) -{ - AH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_BL_imm(uint32_t fetchdat) -{ - BL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_BH_imm(uint32_t fetchdat) -{ - BH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_CL_imm(uint32_t fetchdat) -{ - CL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_CH_imm(uint32_t fetchdat) -{ - CH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_DL_imm(uint32_t fetchdat) -{ - DL = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_DH_imm(uint32_t fetchdat) -{ - DH = getbytef(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); - return 0; -} - -static int opMOV_AX_imm(uint32_t fetchdat) -{ - AX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_BX_imm(uint32_t fetchdat) -{ - BX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_CX_imm(uint32_t fetchdat) -{ - CX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_DX_imm(uint32_t fetchdat) -{ - DX = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_SI_imm(uint32_t fetchdat) -{ - SI = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_DI_imm(uint32_t fetchdat) -{ - DI = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_BP_imm(uint32_t fetchdat) -{ - BP = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_SP_imm(uint32_t fetchdat) -{ - SP = getwordf(); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); - return 0; -} - -static int opMOV_EAX_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EAX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_EBX_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EBX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_ECX_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ECX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_EDX_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EDX = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_ESI_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ESI = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_EDI_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EDI = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_EBP_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - EBP = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} -static int opMOV_ESP_imm(uint32_t fetchdat) -{ - uint32_t templ = getlong(); if (cpu_state.abrt) return 1; - ESP = templ; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); - return 0; -} - -static int opMOV_b_imm_a16(uint32_t fetchdat) -{ - uint8_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = readmemb(cs,cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; - seteab(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); - return cpu_state.abrt; -} -static int opMOV_b_imm_a32(uint32_t fetchdat) -{ - uint8_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getbyte(); if (cpu_state.abrt) return 1; - seteab(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); - return cpu_state.abrt; -} - -static int opMOV_w_imm_a16(uint32_t fetchdat) -{ - uint16_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getword(); if (cpu_state.abrt) return 1; - seteaw(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0); - return cpu_state.abrt; -} -static int opMOV_w_imm_a32(uint32_t fetchdat) -{ - uint16_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getword(); if (cpu_state.abrt) return 1; - seteaw(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1); - return cpu_state.abrt; -} -static int opMOV_l_imm_a16(uint32_t fetchdat) -{ - uint32_t temp; - fetch_ea_16(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getlong(); if (cpu_state.abrt) return 1; - seteal(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 0); - return cpu_state.abrt; -} -static int opMOV_l_imm_a32(uint32_t fetchdat) -{ - uint32_t temp; - fetch_ea_32(fetchdat); - ILLEGAL_ON((rmdat & 0x38) != 0); - SEG_CHECK_WRITE(cpu_state.ea_seg); - temp = getlong(); if (cpu_state.abrt) return 1; - seteal(temp); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 1); - return cpu_state.abrt; -} - - -static int opMOV_AL_a16(uint32_t fetchdat) -{ - uint8_t temp; - uint16_t addr = getwordf(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); - return 0; -} -static int opMOV_AL_a32(uint32_t fetchdat) -{ - uint8_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); - return 0; -} -static int opMOV_AX_a16(uint32_t fetchdat) -{ - uint16_t temp; - uint16_t addr = getwordf(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+1); - temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0); - return 0; -} -static int opMOV_AX_a32(uint32_t fetchdat) -{ - uint16_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+1); - temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1); - return 0; -} -static int opMOV_EAX_a16(uint32_t fetchdat) -{ - uint32_t temp; - uint16_t addr = getwordf(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+3); - temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - EAX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 3, -1, 0,1,0,0, 0); - return 0; -} -static int opMOV_EAX_a32(uint32_t fetchdat) -{ - uint32_t temp; - uint32_t addr = getlong(); - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, addr, addr+3); - temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - EAX = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 5, -1, 0,1,0,0, 1); - return 0; -} - -static int opMOV_a16_AL(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); - writememb(cpu_state.ea_seg->base, addr, AL); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opMOV_a32_AL(uint32_t fetchdat) -{ - uint32_t addr = getlong(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr); - writememb(cpu_state.ea_seg->base, addr, AL); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); - return cpu_state.abrt; -} -static int opMOV_a16_AX(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1); - writememw(cpu_state.ea_seg->base, addr, AX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0); - return cpu_state.abrt; -} -static int opMOV_a32_AX(uint32_t fetchdat) -{ - uint32_t addr = getlong(); if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1); - writememw(cpu_state.ea_seg->base, addr, AX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1); - return cpu_state.abrt; -} -static int opMOV_a16_EAX(uint32_t fetchdat) -{ - uint16_t addr = getwordf(); - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3); - writememl(cpu_state.ea_seg->base, addr, EAX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0); - return cpu_state.abrt; -} -static int opMOV_a32_EAX(uint32_t fetchdat) -{ - uint32_t addr = getlong(); if (cpu_state.abrt) return 1; - SEG_CHECK_WRITE(cpu_state.ea_seg); - CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3); - writememl(cpu_state.ea_seg->base, addr, EAX); - CLOCK_CYCLES((is486) ? 1 : 2); - PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1); - return cpu_state.abrt; -} - - -static int opLEA_w_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opLEA_w_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].w = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - return 0; -} - -static int opLEA_l_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr & 0xffff; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - return 0; -} -static int opLEA_l_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - cpu_state.regs[cpu_reg].l = cpu_state.eaaddr; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - return 0; -} - - - -static int opXLAT_a16(uint32_t fetchdat) -{ - uint32_t addr = (BX + AL)&0xFFFF; - uint8_t temp; - - SEG_CHECK_READ(cpu_state.ea_seg); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0); - return 0; -} -static int opXLAT_a32(uint32_t fetchdat) -{ - uint32_t addr = EBX + AL; - uint8_t temp; - - SEG_CHECK_READ(cpu_state.ea_seg); - temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1; - AL = temp; - CLOCK_CYCLES(5); - PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1); - return 0; -} - -static int opMOV_b_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_rm, getr8(cpu_reg)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(getr8(cpu_reg)); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); - } - return cpu_state.abrt; -} -static int opMOV_b_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_rm, getr8(cpu_reg)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteab(getr8(cpu_reg)); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); - } - return cpu_state.abrt; -} -static int opMOV_w_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.regs[cpu_reg].w); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0); - } - return cpu_state.abrt; -} -static int opMOV_w_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw(cpu_state.regs[cpu_reg].w); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1); - } - return cpu_state.abrt; -} -static int opMOV_l_r_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(cpu_state.regs[cpu_reg].l); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 0); - } - return cpu_state.abrt; -} -static int opMOV_l_r_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteal(cpu_state.regs[cpu_reg].l); - CLOCK_CYCLES(is486 ? 1 : 2); - PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 1); - } - return cpu_state.abrt; -} - -static int opMOV_r_b_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_reg, getr8(cpu_rm)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - temp = geteab(); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); - } - return 0; -} -static int opMOV_r_b_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - setr8(cpu_reg, getr8(cpu_rm)); - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint8_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); - temp = geteab(); if (cpu_state.abrt) return 1; - setr8(cpu_reg, temp); - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); - } - return 0; -} -static int opMOV_r_w_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0); - } - return 0; -} -static int opMOV_r_w_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint16_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - CLOCK_CYCLES((is486) ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1); - } - return 0; -} -static int opMOV_r_l_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); - } - else - { - uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); - temp = geteal(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 0); - } - return 0; -} -static int opMOV_r_l_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod == 3) - { - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; - CLOCK_CYCLES(timing_rr); - PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); - } - else - { - uint32_t temp; - SEG_CHECK_READ(cpu_state.ea_seg); - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); - temp = geteal(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp; - CLOCK_CYCLES(is486 ? 1 : 4); - PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 1); - } - return 0; -} - -#define opCMOV(condition) \ - static int opCMOV ## condition ## _w_a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ - else \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _w_a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \ - else \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \ - temp = geteaw(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _l_a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ - else \ - { \ - uint32_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } \ - static int opCMOV ## condition ## _l_a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cond_ ## condition) \ - { \ - if (cpu_mod == 3) \ - cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \ - else \ - { \ - uint32_t temp; \ - CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - temp = geteal(); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = temp; \ - } \ - } \ - CLOCK_CYCLES(1); \ - return 0; \ - } - -opCMOV(O) -opCMOV(NO) -opCMOV(B) -opCMOV(NB) -opCMOV(E) -opCMOV(NE) -opCMOV(BE) -opCMOV(NBE) -opCMOV(S) -opCMOV(NS) -opCMOV(P) -opCMOV(NP) -opCMOV(L) -opCMOV(NL) -opCMOV(LE) -opCMOV(NLE) diff --git a/src/cpu_new/x86_ops_mov_seg.h b/src/cpu_new/x86_ops_mov_seg.h deleted file mode 100644 index da7727143..000000000 --- a/src/cpu_new/x86_ops_mov_seg.h +++ /dev/null @@ -1,434 +0,0 @@ -static int opMOV_w_seg_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - seteaw(DS); - break; - case 0x10: /*SS*/ - seteaw(SS); - break; - case 0x20: /*FS*/ - seteaw(FS); - break; - case 0x28: /*GS*/ - seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_w_seg_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - seteaw(DS); - break; - case 0x10: /*SS*/ - seteaw(SS); - break; - case 0x20: /*FS*/ - seteaw(FS); - break; - case 0x28: /*GS*/ - seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; -} - -static int opMOV_l_seg_a16(uint32_t fetchdat) -{ - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES; - else seteaw(ES); - break; - case 0x08: /*CS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS; - else seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS; - else seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS; - else seteaw(SS); - break; - case 0x20: /*FS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS; - else seteaw(FS); - break; - case 0x28: /*GS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS; - else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_l_seg_a32(uint32_t fetchdat) -{ - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_WRITE(cpu_state.ea_seg); - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES; - else seteaw(ES); - break; - case 0x08: /*CS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS; - else seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS; - else seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS; - else seteaw(SS); - break; - case 0x20: /*FS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS; - else seteaw(FS); - break; - case 0x28: /*GS*/ - if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS; - else seteaw(GS); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; -} - -static int opMOV_seg_w_a16(uint32_t fetchdat) -{ - uint16_t new_seg; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_seg=geteaw(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - loadseg(new_seg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - loadseg(new_seg, &cpu_state.seg_ds); - break; - case 0x10: /*SS*/ - loadseg(new_seg, &cpu_state.seg_ss); - if (cpu_state.abrt) return 1; - 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; - case 0x20: /*FS*/ - loadseg(new_seg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - loadseg(new_seg, &cpu_state.seg_gs); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0); - return cpu_state.abrt; -} -static int opMOV_seg_w_a32(uint32_t fetchdat) -{ - uint16_t new_seg; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - new_seg=geteaw(); if (cpu_state.abrt) return 1; - - switch (rmdat & 0x38) - { - case 0x00: /*ES*/ - loadseg(new_seg, &cpu_state.seg_es); - break; - case 0x18: /*DS*/ - loadseg(new_seg, &cpu_state.seg_ds); - break; - case 0x10: /*SS*/ - loadseg(new_seg, &cpu_state.seg_ss); - if (cpu_state.abrt) return 1; - 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; - case 0x20: /*FS*/ - loadseg(new_seg, &cpu_state.seg_fs); - break; - case 0x28: /*GS*/ - loadseg(new_seg, &cpu_state.seg_gs); - break; - } - - CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5); - PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1); - return cpu_state.abrt; -} - - -static int opLDS_w_a16(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); - return 0; -} -static int opLDS_w_a32(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); - return 0; -} -static int opLDS_l_a16(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); - return 0; -} -static int opLDS_l_a32(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); - return 0; -} - -static int opLSS_w_a16(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); - return 1; -} -static int opLSS_w_a32(uint32_t fetchdat) -{ - uint16_t addr, seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmemw(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); - return 1; -} -static int opLSS_l_a16(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_16(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); - return 1; -} -static int opLSS_l_a32(uint32_t fetchdat) -{ - uint32_t addr; - uint16_t seg; - - fetch_ea_32(fetchdat); - ILLEGAL_ON(cpu_mod == 3); - SEG_CHECK_READ(cpu_state.ea_seg); - addr = readmeml(easeg, cpu_state.eaaddr); - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; - loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = addr; - - CLOCK_CYCLES(7); - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); - return 1; -} - -#define opLsel(name, sel) \ - static int opL ## name ## _w_a16(uint32_t fetchdat) \ - { \ - uint16_t addr, seg; \ - \ - fetch_ea_16(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - addr = readmemw(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); \ - return 0; \ - } \ - \ - static int opL ## name ## _w_a32(uint32_t fetchdat) \ - { \ - uint16_t addr, seg; \ - \ - fetch_ea_32(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - addr = readmemw(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].w = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); \ - return 0; \ - } \ - \ - static int opL ## name ## _l_a16(uint32_t fetchdat) \ - { \ - uint32_t addr; \ - uint16_t seg; \ - \ - fetch_ea_16(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - addr = readmeml(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); \ - return 0; \ - } \ - \ - static int opL ## name ## _l_a32(uint32_t fetchdat) \ - { \ - uint32_t addr; \ - uint16_t seg; \ - \ - fetch_ea_32(fetchdat); \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - ILLEGAL_ON(cpu_mod == 3); \ - addr = readmeml(easeg, cpu_state.eaaddr); \ - seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \ - loadseg(seg, &sel); if (cpu_state.abrt) return 1; \ - cpu_state.regs[cpu_reg].l = addr; \ - \ - CLOCK_CYCLES(7); \ - PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); \ - return 0; \ - } - -opLsel(ES, cpu_state.seg_es) -opLsel(FS, cpu_state.seg_fs) -opLsel(GS, cpu_state.seg_gs) diff --git a/src/cpu_new/x86_ops_movx.h b/src/cpu_new/x86_ops_movx.h deleted file mode 100644 index 2e4fa2001..000000000 --- a/src/cpu_new/x86_ops_movx.h +++ /dev/null @@ -1,209 +0,0 @@ -static int opMOVZX_w_b_a16(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVZX_w_b_a32(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opMOVZX_l_b_a16(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVZX_l_b_a32(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opMOVZX_w_w_a16(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVZX_w_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opMOVZX_l_w_a16(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVZX_l_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} - -static int opMOVSX_w_b_a16(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].w |= 0xff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVSX_w_b_a32(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = (uint16_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].w |= 0xff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opMOVSX_l_b_a16(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].l |= 0xffffff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVSX_l_b_a32(uint32_t fetchdat) -{ - uint8_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteab(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x80) - cpu_state.regs[cpu_reg].l |= 0xffffff00; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} -static int opMOVSX_l_w_a16(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x8000) - cpu_state.regs[cpu_reg].l |= 0xffff0000; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); - return 0; -} -static int opMOVSX_l_w_a32(uint32_t fetchdat) -{ - uint16_t temp; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - temp = geteaw(); if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = (uint32_t)temp; - if (temp & 0x8000) - cpu_state.regs[cpu_reg].l |= 0xffff0000; - - CLOCK_CYCLES(3); - PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); - return 0; -} diff --git a/src/cpu_new/x86_ops_msr.h b/src/cpu_new/x86_ops_msr.h deleted file mode 100644 index 2a8bdcf4c..000000000 --- a/src/cpu_new/x86_ops_msr.h +++ /dev/null @@ -1,30 +0,0 @@ -static int opRDTSC(uint32_t fetchdat) -{ - if (!cpu_has_feature(CPU_FEATURE_RDTSC)) - { - cpu_state.pc = cpu_state.oldpc; - x86illegal(); - return 1; - } - if ((cr4 & CR4_TSD) && CPL) - { - x86gpf("RDTSC when TSD set and CPL != 0", 0); - return 1; - } - EAX = tsc & 0xffffffff; - EDX = tsc >> 32; - CLOCK_CYCLES(1); - return 0; -} - -static int opRDPMC(uint32_t fetchdat) -{ - if (ECX > 1 || (!(cr4 & CR4_PCE) && (cr0 & 1) && CPL)) - { - x86gpf("RDPMC not allowed", 0); - return 1; - } - EAX = EDX = 0; - CLOCK_CYCLES(1); - return 0; -} diff --git a/src/cpu_new/x86_ops_mul.h b/src/cpu_new/x86_ops_mul.h deleted file mode 100644 index f3e10e5a0..000000000 --- a/src/cpu_new/x86_ops_mul.h +++ /dev/null @@ -1,264 +0,0 @@ -static int opIMUL_w_iw_a16(uint32_t fetchdat) -{ - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getword(); if (cpu_state.abrt) return 1; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 0); - return 0; -} -static int opIMUL_w_iw_a32(uint32_t fetchdat) -{ - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getword(); if (cpu_state.abrt) return 1; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 1); - return 0; -} - -static int opIMUL_l_il_a16(uint32_t fetchdat) -{ - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getlong(); if (cpu_state.abrt) return 1; - - temp64 = ((int64_t)templ) * ((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(25); - PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 0); - return 0; -} -static int opIMUL_l_il_a32(uint32_t fetchdat) -{ - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getlong(); if (cpu_state.abrt) return 1; - - temp64 = ((int64_t)templ) * ((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(25); - PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 1); - return 0; -} - -static int opIMUL_w_ib_a16(uint32_t fetchdat) -{ - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getbyte(); if (cpu_state.abrt) return 1; - if (tempw2 & 0x80) tempw2 |= 0xff00; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 0); - return 0; -} -static int opIMUL_w_ib_a32(uint32_t fetchdat) -{ - int32_t templ; - int16_t tempw, tempw2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - tempw = geteaw(); if (cpu_state.abrt) return 1; - tempw2 = getbyte(); if (cpu_state.abrt) return 1; - if (tempw2 & 0x80) tempw2 |= 0xff00; - - templ = ((int)tempw) * ((int)tempw2); - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].w = templ & 0xffff; - - CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17); - PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 1); - return 0; -} - -static int opIMUL_l_ib_a16(uint32_t fetchdat) -{ - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getbyte(); if (cpu_state.abrt) return 1; - if (templ2 & 0x80) templ2 |= 0xffffff00; - - temp64 = ((int64_t)templ)*((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 0); - return 0; -} -static int opIMUL_l_ib_a32(uint32_t fetchdat) -{ - int64_t temp64; - int32_t templ, templ2; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = geteal(); if (cpu_state.abrt) return 1; - templ2 = getbyte(); if (cpu_state.abrt) return 1; - if (templ2 & 0x80) templ2 |= 0xffffff00; - - temp64 = ((int64_t)templ)*((int64_t)templ2); - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff; - - CLOCK_CYCLES(20); - PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 1); - return 0; -} - - - -static int opIMUL_w_w_a16(uint32_t fetchdat) -{ - int32_t templ; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = templ & 0xFFFF; - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(18); - PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 0); - return 0; -} -static int opIMUL_w_w_a32(uint32_t fetchdat) -{ - int32_t templ; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].w = templ & 0xFFFF; - flags_rebuild(); - if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(18); - PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 1); - return 0; -} - -static int opIMUL_l_l_a16(uint32_t fetchdat) -{ - int64_t temp64; - - fetch_ea_16(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(30); - PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 0); - return 0; -} -static int opIMUL_l_l_a32(uint32_t fetchdat) -{ - int64_t temp64; - - fetch_ea_32(fetchdat); - if (cpu_mod != 3) - SEG_CHECK_READ(cpu_state.ea_seg); - - temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal(); - if (cpu_state.abrt) return 1; - cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF; - flags_rebuild(); - if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG; - else cpu_state.flags &= ~(C_FLAG | V_FLAG); - - CLOCK_CYCLES(30); - PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 1); - return 0; -} - diff --git a/src/cpu_new/x86_ops_prefix.h b/src/cpu_new/x86_ops_prefix.h deleted file mode 100644 index 8d191103d..000000000 --- a/src/cpu_new/x86_ops_prefix.h +++ /dev/null @@ -1,161 +0,0 @@ -#define op_seg(name, seg, opcode_table, normal_opcode_table) \ -static int op ## name ## _w_a16(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[fetchdat & 0xff]) \ - return opcode_table[fetchdat & 0xff](fetchdat >> 8); \ - return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _l_a16(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x100]) \ - return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ - return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _w_a32(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x200]) \ - return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ - return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \ -} \ - \ -static int op ## name ## _l_a32(uint32_t fetchdat) \ -{ \ - fetchdat = fastreadl(cs + cpu_state.pc); \ - if (cpu_state.abrt) return 1; \ - cpu_state.pc++; \ - \ - cpu_state.ea_seg = &seg; \ - cpu_state.ssegs = 1; \ - CLOCK_CYCLES(4); \ - PREFETCH_PREFIX(); \ - \ - if (opcode_table[(fetchdat & 0xff) | 0x300]) \ - return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ - return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \ -} - -op_seg(CS, cpu_state.seg_cs, x86_opcodes, x86_opcodes) -op_seg(DS, cpu_state.seg_ds, x86_opcodes, x86_opcodes) -op_seg(ES, cpu_state.seg_es, x86_opcodes, x86_opcodes) -op_seg(FS, cpu_state.seg_fs, x86_opcodes, x86_opcodes) -op_seg(GS, cpu_state.seg_gs, x86_opcodes, x86_opcodes) -op_seg(SS, cpu_state.seg_ss, x86_opcodes, x86_opcodes) - -op_seg(CS_REPE, cpu_state.seg_cs, x86_opcodes_REPE, x86_opcodes) -op_seg(DS_REPE, cpu_state.seg_ds, x86_opcodes_REPE, x86_opcodes) -op_seg(ES_REPE, cpu_state.seg_es, x86_opcodes_REPE, x86_opcodes) -op_seg(FS_REPE, cpu_state.seg_fs, x86_opcodes_REPE, x86_opcodes) -op_seg(GS_REPE, cpu_state.seg_gs, x86_opcodes_REPE, x86_opcodes) -op_seg(SS_REPE, cpu_state.seg_ss, x86_opcodes_REPE, x86_opcodes) - -op_seg(CS_REPNE, cpu_state.seg_cs, x86_opcodes_REPNE, x86_opcodes) -op_seg(DS_REPNE, cpu_state.seg_ds, x86_opcodes_REPNE, x86_opcodes) -op_seg(ES_REPNE, cpu_state.seg_es, x86_opcodes_REPNE, x86_opcodes) -op_seg(FS_REPNE, cpu_state.seg_fs, x86_opcodes_REPNE, x86_opcodes) -op_seg(GS_REPNE, cpu_state.seg_gs, x86_opcodes_REPNE, x86_opcodes) -op_seg(SS_REPNE, cpu_state.seg_ss, x86_opcodes_REPNE, x86_opcodes) - -static int op_66(uint32_t fetchdat) /*Data size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} -static int op_67(uint32_t fetchdat) /*Address size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} - -static int op_66_REPE(uint32_t fetchdat) /*Data size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} -static int op_67_REPE(uint32_t fetchdat) /*Address size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} -static int op_66_REPNE(uint32_t fetchdat) /*Data size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} -static int op_67_REPNE(uint32_t fetchdat) /*Address size select*/ -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100); - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} diff --git a/src/cpu_new/x86_ops_rep.h b/src/cpu_new/x86_ops_rep.h deleted file mode 100644 index efbb088ef..000000000 --- a/src/cpu_new/x86_ops_rep.h +++ /dev/null @@ -1,713 +0,0 @@ -#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \ -static int opREP_INSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint8_t temp; \ - \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - temp = inb(DX); \ - writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_INSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint16_t temp; \ - \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - temp = inw(DX); \ - writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_INSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - 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); \ - CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - temp = inl(DX); \ - writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= 15; \ - reads++; writes++; total_cycles += 15; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_OUTSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint8_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - check_io_perm(DX); \ - outb(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_OUTSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint16_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - check_io_perm(DX); \ - check_io_perm(DX+1); \ - outw(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_OUTSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - \ - if (CNT_REG > 0) \ - { \ - uint32_t temp; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); 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); \ - outl(DX, temp); \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ - CNT_REG--; \ - cycles -= 14; \ - reads++; writes++; total_cycles += 14; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_MOVSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint8_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - ins++; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_MOVSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint16_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - ins++; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_MOVSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - { \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - } \ - while (CNT_REG > 0) \ - { \ - uint32_t temp; \ - \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ - CNT_REG--; \ - cycles -= is486 ? 3 : 4; \ - ins++; \ - reads++; writes++; total_cycles += is486 ? 3 : 4; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ - \ -static int opREP_STOSB_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_STOSW_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_STOSL_ ## size(uint32_t fetchdat) \ -{ \ - int writes = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_WRITE(&cpu_state.seg_es); \ - while (CNT_REG > 0) \ - { \ - CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - writes++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_LODSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG--; \ - else SRC_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_LODSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \ - AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \ - else SRC_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_LODSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - if (CNT_REG > 0) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - while (CNT_REG > 0) \ - { \ - CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \ - EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \ - if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \ - else SRC_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 4 : 5; \ - reads++; total_cycles += is486 ? 4 : 5; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if (CNT_REG > 0) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - - -#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \ -static int opREP_CMPSB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint8_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \ - else { DEST_REG++; SRC_REG++; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub8(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_CMPSW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint16_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \ - else { DEST_REG += 2; SRC_REG += 2; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub16(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_CMPSL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - uint32_t temp, temp2; \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \ - CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \ - temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \ - \ - if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \ - else { DEST_REG += 4; SRC_REG += 4; } \ - CNT_REG--; \ - cycles -= is486 ? 7 : 9; \ - reads += 2; total_cycles += is486 ? 7 : 9; \ - setsub32(temp, temp2); \ - tempz = (ZF_SET()) ? 1 : 0; \ - } \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ - \ -static int opREP_SCASB_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \ - uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub8(AL, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG--; \ - else DEST_REG++; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_SCASW_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \ - uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub16(AX, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \ - else DEST_REG += 2; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} \ -static int opREP_SCASL_ ## size(uint32_t fetchdat) \ -{ \ - int reads = 0, total_cycles = 0, tempz; \ - int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \ - if (trap) \ - cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \ - tempz = FV; \ - if ((CNT_REG > 0) && (FV == tempz)) \ - SEG_CHECK_READ(&cpu_state.seg_es); \ - while ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \ - uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\ - setsub32(EAX, temp); \ - tempz = (ZF_SET()) ? 1 : 0; \ - if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \ - else DEST_REG += 4; \ - CNT_REG--; \ - cycles -= is486 ? 5 : 8; \ - reads++; total_cycles += is486 ? 5 : 8; \ - ins++; \ - if (cycles < cycles_end) \ - break; \ - } \ - ins--; \ - PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \ - if ((CNT_REG > 0) && (FV == tempz)) \ - { \ - CPU_BLOCK_END(); \ - cpu_state.pc = cpu_state.oldpc; \ - return 1; \ - } \ - return cpu_state.abrt; \ -} - -REP_OPS(a16, CX, SI, DI) -REP_OPS(a32, ECX, ESI, EDI) -REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0) -REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1) -REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0) -REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1) - -static int opREPNE(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} -static int opREPE(uint32_t fetchdat) -{ - fetchdat = fastreadl(cs + cpu_state.pc); - if (cpu_state.abrt) return 1; - cpu_state.pc++; - - CLOCK_CYCLES(2); - PREFETCH_PREFIX(); - if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32]) - return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); - return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8); -} diff --git a/src/cpu_new/x86_ops_ret.h b/src/cpu_new/x86_ops_ret.h deleted file mode 100644 index 133c6153b..000000000 --- a/src/cpu_new/x86_ops_ret.h +++ /dev/null @@ -1,256 +0,0 @@ -#define RETF_a16(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ - { \ - pmoderetf(0, stack_offset); \ - return 1; \ - } \ - if (stack32) \ - { \ - cpu_state.pc = readmemw(ss, ESP); \ - loadcs(readmemw(ss, ESP + 2)); \ - } \ - else \ - { \ - cpu_state.pc = readmemw(ss, SP); \ - loadcs(readmemw(ss, SP + 2)); \ - } \ - if (cpu_state.abrt) return 1; \ - if (stack32) ESP += 4 + stack_offset; \ - else SP += 4 + stack_offset; \ - cycles -= timing_retf_rm; - -#define RETF_a32(stack_offset) \ - if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \ - { \ - pmoderetf(1, stack_offset); \ - return 1; \ - } \ - if (stack32) \ - { \ - cpu_state.pc = readmeml(ss, ESP); \ - loadcs(readmeml(ss, ESP + 4) & 0xffff); \ - } \ - else \ - { \ - cpu_state.pc = readmeml(ss, SP); \ - loadcs(readmeml(ss, SP + 4) & 0xffff); \ - } \ - if (cpu_state.abrt) return 1; \ - if (stack32) ESP += 8 + stack_offset; \ - else SP += 8 + stack_offset; \ - cycles -= timing_retf_rm; - -static int opRETF_a16(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a16(0); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; -} -static int opRETF_a32(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a32(0); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return 0; -} - -static int opRETF_a16_imm(uint32_t fetchdat) -{ - uint16_t offset = getwordf(); - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a16(offset); - - PREFETCH_RUN(cycles_old-cycles, 3, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return 0; -} -static int opRETF_a32_imm(uint32_t fetchdat) -{ - uint16_t offset = getwordf(); - int cycles_old = cycles; UN_USED(cycles_old); - - CPU_BLOCK_END(); - RETF_a32(offset); - - PREFETCH_RUN(cycles_old-cycles, 3, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return 0; -} - -static int opIRET_286(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - if (msw&1) - { - optype = IRET; - pmodeiret(0); - optype = 0; - } - else - { - uint16_t new_cs; - if (stack32) - { - cpu_state.pc = readmemw(ss, ESP); - new_cs = readmemw(ss, ESP + 2); - cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2; - ESP += 6; - } - else - { - cpu_state.pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2; - SP += 6; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return cpu_state.abrt; -} - -static int opIRET(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - if (cr4 & CR4_VME) - { - uint16_t new_pc, new_cs, new_flags; - - new_pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - new_flags = readmemw(ss, ((SP + 4) & 0xffff)); - if (cpu_state.abrt) - return 1; - - if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) - { - x86gpf(NULL, 0); - return 1; - } - SP += 6; - if (new_flags & I_FLAG) - cpu_state.eflags |= VIF_FLAG; - else - cpu_state.eflags &= ~VIF_FLAG; - cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2; - loadcs(new_cs); - cpu_state.pc = new_pc; - - cycles -= timing_iret_rm; - } - else - { - x86gpf(NULL,0); - return 1; - } - } - else - { - if (msw&1) - { - optype = IRET; - pmodeiret(0); - optype = 0; - } - else - { - uint16_t new_cs; - if (stack32) - { - cpu_state.pc = readmemw(ss, ESP); - new_cs = readmemw(ss, ESP + 2); - cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2; - ESP += 6; - } - else - { - cpu_state.pc = readmemw(ss, SP); - new_cs = readmemw(ss, ((SP + 2) & 0xffff)); - cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2; - SP += 6; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0); - PREFETCH_FLUSH(); - return cpu_state.abrt; -} - -static int opIRETD(uint32_t fetchdat) -{ - int cycles_old = cycles; UN_USED(cycles_old); - - if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) - { - x86gpf(NULL,0); - return 1; - } - if (msw & 1) - { - optype = IRET; - pmodeiret(1); - optype = 0; - } - else - { - uint16_t new_cs; - if (stack32) - { - cpu_state.pc = readmeml(ss, ESP); - new_cs = readmemw(ss, ESP + 4); - cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2; - cpu_state.eflags = readmemw(ss, ESP + 10); - ESP += 12; - } - else - { - cpu_state.pc = readmeml(ss, SP); - new_cs = readmemw(ss, ((SP + 4) & 0xffff)); - cpu_state.flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2; - cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff); - SP += 12; - } - loadcs(new_cs); - cycles -= timing_iret_rm; - } - flags_extract(); - nmi_enable = 1; - CPU_BLOCK_END(); - - PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1); - PREFETCH_FLUSH(); - return cpu_state.abrt; -} - diff --git a/src/cpu_new/x86_ops_set.h b/src/cpu_new/x86_ops_set.h deleted file mode 100644 index f6fd50e69..000000000 --- a/src/cpu_new/x86_ops_set.h +++ /dev/null @@ -1,37 +0,0 @@ -#define opSET(condition) \ - static int opSET ## condition ## _a16(uint32_t fetchdat) \ - { \ - fetch_ea_16(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - seteab((cond_ ## condition) ? 1 : 0); \ - CLOCK_CYCLES(4); \ - return cpu_state.abrt; \ - } \ - \ - static int opSET ## condition ## _a32(uint32_t fetchdat) \ - { \ - fetch_ea_32(fetchdat); \ - if (cpu_mod != 3) \ - SEG_CHECK_READ(cpu_state.ea_seg); \ - seteab((cond_ ## condition) ? 1 : 0); \ - CLOCK_CYCLES(4); \ - return cpu_state.abrt; \ - } - -opSET(O) -opSET(NO) -opSET(B) -opSET(NB) -opSET(E) -opSET(NE) -opSET(BE) -opSET(NBE) -opSET(S) -opSET(NS) -opSET(P) -opSET(NP) -opSET(L) -opSET(NL) -opSET(LE) -opSET(NLE) diff --git a/src/cpu_new/x86seg.c b/src/cpu_new/x86seg.c index 2a438d862..12ad3753b 100644 --- a/src/cpu_new/x86seg.c +++ b/src/cpu_new/x86seg.c @@ -24,13 +24,13 @@ #include #include #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" @@ -761,6 +761,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); @@ -1228,6 +1229,7 @@ void loadcscall(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); @@ -1762,6 +1764,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)) { diff --git a/src/cpu_new/x86seg.h b/src/cpu_new/x86seg.h deleted file mode 100644 index 4f12a8d65..000000000 --- a/src/cpu_new/x86seg.h +++ /dev/null @@ -1,18 +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 CPU segment emulation. - * - * Version: @(#)x86seg.h 1.0.1 2017/10/12 - * - * Author: Miran Grca, - * - * Copyright 2016-2017 Miran Grca. - */ - -extern void do_seg_load(x86seg *s, uint16_t *segdat); diff --git a/src/device.c b/src/device.c index 97318c50d..dddf24551 100644 --- a/src/device.c +++ b/src/device.c @@ -47,8 +47,8 @@ #include "86box.h" #include "config.h" #include "device.h" -#include "machine/machine.h" -#include "sound/sound.h" +#include "machine.h" +#include "sound.h" #define DEVICE_MAX 256 /* max # of devices */ diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 4b1313cb1..f6ed1ae35 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -22,9 +22,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../machine/machine.h" -#include "../device.h" +#include "86box.h" +#include "machine.h" +#include "device.h" #include "hdc.h" #include "hdc_ide.h" #include "hdd.h" diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index 6e3946a80..91f1071a4 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -28,17 +28,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../pic.h" -#include "../rom.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "mem.h" +#include "pic.h" +#include "rom.h" +#include "cpu.h" +#include "machine.h" +#include "timer.h" +#include "plat.h" +#include "ui.h" #include "hdc.h" #include "hdd.h" @@ -304,6 +304,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) esdi->command &= ~0x03; if (val & 0x02) fatal("Read with ECC\n"); + /*FALLTHROUGH*/ case 0xa0: esdi->status = STAT_BUSY; @@ -351,6 +352,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv) default: esdi_at_log("WD1007: bad command %02X\n", val); + /*FALLTHROUGH*/ case 0xe8: /*???*/ esdi->status = STAT_BUSY; timer_set_delay_u64(&esdi->callback_timer, 200 * HDC_TIME); diff --git a/src/disk/hdc_esdi_mca.c b/src/disk/hdc_esdi_mca.c index f70dd7db7..c3438e8dd 100644 --- a/src/disk/hdc_esdi_mca.c +++ b/src/disk/hdc_esdi_mca.c @@ -67,16 +67,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../dma.h" -#include "../io.h" -#include "../mca.h" -#include "../mem.h" -#include "../pic.h" -#include "../rom.h" -#include "../timer.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "dma.h" +#include "86box_io.h" +#include "mca.h" +#include "mem.h" +#include "pic.h" +#include "rom.h" +#include "timer.h" +#include "ui.h" #include "hdc.h" #include "hdd.h" diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index a9d1e8e59..3e6c4a6f1 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -9,13 +9,13 @@ * Implementation of the IDE emulation for hard disks and ATAPI * CD-ROM devices. * - * Version: @(#)hdc_ide.c 1.0.65 2019/11/19 + * Version: @(#)hdc_ide.c 1.0.66 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #define __USE_LARGEFILE64 #define _LARGEFILE_SOURCE @@ -28,20 +28,20 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../mem.h" -#include "../pic.h" -#include "../pci.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../scsi/scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "86box_io.h" +#include "mem.h" +#include "pic.h" +#include "pci.h" +#include "rom.h" +#include "timer.h" +#include "device.h" +#include "scsi_device.h" +#include "cdrom.h" +#include "plat.h" +#include "ui.h" #include "hdc.h" #include "hdc_ide.h" #include "hdd.h" @@ -249,8 +249,6 @@ ide_get_period(ide_t *ide, int size) break; } - period = (10.0 / 3.0); - period = (1.0 / period); /* get us for 1 byte */ return period * ((double) size); /* multiply by bytes to get period for the entire transfer */ } @@ -280,6 +278,8 @@ ide_irq_raise(ide_t *ide) /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ + ide_log("IDE %i: IRQ raise\n", ide->board); + if (!(ide->fdisk & 2)) { if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq) ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); @@ -300,6 +300,8 @@ ide_irq_lower(ide_t *ide) /* ide_log("Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ + ide_log("IDE %i: IRQ lower\n", ide->board); + if (ide->irqstat) { if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq) ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); @@ -320,6 +322,7 @@ ide_irq_update(ide_t *ide) /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ if (!(ide->fdisk & 2) && ide->irqstat) { + ide_log("IDE %i: IRQ update raise\n", ide->board); if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq) { ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); ide_bm[ide->board]->set_irq(ide->board | 0x40, ide_bm[ide->board]->priv); @@ -328,6 +331,7 @@ ide_irq_update(ide_t *ide) picint(1 << ide_boards[ide->board]->irq); } } else if (ide->fdisk & 2) { + ide_log("IDE %i: IRQ update lower\n", ide->board); if (ide_bm[ide->board] && ide_bm[ide->board]->set_irq) ide_bm[ide->board]->set_irq(ide->board, ide_bm[ide->board]->priv); else if (ide_boards[ide->board]->irq != -1) @@ -450,7 +454,7 @@ static void ide_hd_identify(ide_t *ide) char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; uint32_t d_hpc, d_spt, d_tracks; - uint64_t full_size = (hdd[ide->hdd_num].tracks * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); device_identify[6] = (ide->hdd_num / 10) + 0x30; device_identify[7] = (ide->hdd_num % 10) + 0x30; @@ -759,6 +763,7 @@ ide_set_features(ide_t *ide) default: return 0; } + break; case FEATURE_ENABLE_IRQ_OVERLAPPED: case FEATURE_ENABLE_IRQ_SERVICE: @@ -878,11 +883,17 @@ ide_atapi_callback(ide_t *ide) switch(ide->sc->packet_status) { case PHASE_IDLE: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_IDLE\n"); +#endif ide->sc->pos = 0; ide->sc->phase = 1; ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); return; case PHASE_COMMAND: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_COMMAND\n"); +#endif ide->sc->status = BUSY_STAT | (ide->sc->status & ERR_STAT); if (ide->packet_command) { ide->packet_command(ide->sc, ide->sc->atapi_cdb); @@ -891,6 +902,9 @@ ide_atapi_callback(ide_t *ide) } return; case PHASE_COMPLETE: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_COMPLETE\n"); +#endif ide->sc->status = READY_STAT; ide->sc->phase = 3; ide->sc->packet_status = PHASE_NONE; @@ -898,12 +912,18 @@ ide_atapi_callback(ide_t *ide) return; case PHASE_DATA_IN: case PHASE_DATA_OUT: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_DATA_IN or PHASE_DATA_OUT\n"); +#endif ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); ide->sc->phase = !(ide->sc->packet_status & 0x01) << 1; ide_irq_raise(ide); return; case PHASE_DATA_IN_DMA: case PHASE_DATA_OUT_DMA: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_DATA_IN_DMA or PHASE_DATA_OUT_DMA\n"); +#endif out = (ide->sc->packet_status & 0x01); if (ide_bm[ide->board] && ide_bm[ide->board]->dma) { @@ -933,11 +953,17 @@ ide_atapi_callback(ide_t *ide) return; case PHASE_ERROR: +#ifdef ENABLE_IDE_LOG + ide_log("PHASE_ERROR\n"); +#endif ide->sc->status = READY_STAT | ERR_STAT; ide->sc->phase = 3; ide->sc->packet_status = PHASE_NONE; ide_irq_raise(ide); return; + default: + ide_log("PHASE_UNKNOWN %02X\n", ide->sc->packet_status); + return; } } @@ -1002,6 +1028,9 @@ ide_atapi_packet_read(ide_t *ide, int length) if (!dev || !dev->temp_buffer || (dev->packet_status != PHASE_DATA_IN)) return 0; + if (dev->packet_status == PHASE_DATA_IN) + ide_log("PHASE_DATA_IN read: %i, %i< %i, %i\n", dev->request_pos, dev->max_transfer_len, dev->pos, dev->packet_len); + bufferw = (uint16_t *) dev->temp_buffer; bufferl = (uint32_t *) dev->temp_buffer; @@ -1461,6 +1490,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) /* Turn on the activity indicator *here* so that it gets turned on less times. */ ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + /*FALLTHROUGH*/ case WIN_READ: case WIN_READ_NORETRY: @@ -1494,6 +1524,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) /* Turn on the activity indicator *here* so that it gets turned on less times. */ ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + /*FALLTHROUGH*/ case WIN_WRITE: case WIN_WRITE_NORETRY: @@ -1688,7 +1719,7 @@ ide_read_data(ide_t *ide, int length) ide->secount = (ide->secount - 1) & 0xff; if (ide->secount) { ide_next_sector(ide); - ide->atastat = BSY_STAT; + ide->atastat = BSY_STAT | READY_STAT | DSC_STAT; if (ide->command == WIN_READ_MULTIPLE) ide_callback(ide_boards[ide->board]); else @@ -1922,7 +1953,7 @@ ide_callback(void *priv) ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { if (ide->type != IDE_HDD) goto abort_cmd; - if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F)) { + if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F) && !ide->lba) { if ((ide->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || !ide->sector || (ide->sector > ide->spt)) goto id_not_found; @@ -1983,7 +2014,7 @@ ide_callback(void *priv) ide_set_signature(ide); goto abort_cmd; } - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; if (ide->do_initial_read) { @@ -2013,7 +2044,7 @@ ide_callback(void *priv) ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); goto abort_cmd; } - if (ide->cfg_spt == 0) { + if (!ide->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); goto id_not_found; } @@ -2065,7 +2096,7 @@ ide_callback(void *priv) mand error. */ if ((ide->type == IDE_ATAPI) || !ide->blocksize) goto abort_cmd; - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; if (ide->do_initial_read) { @@ -2094,7 +2125,7 @@ ide_callback(void *priv) case WIN_WRITE_NORETRY: if (ide->type == IDE_ATAPI) goto abort_cmd; - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide_irq_raise(ide); @@ -2116,7 +2147,7 @@ ide_callback(void *priv) ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); goto abort_cmd; } - if (ide->cfg_spt == 0) { + if (!ide->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); goto id_not_found; } @@ -2161,7 +2192,7 @@ ide_callback(void *priv) case WIN_WRITE_MULTIPLE: if (ide->type == IDE_ATAPI) goto abort_cmd; - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); ide->blockcount++; @@ -2184,7 +2215,7 @@ ide_callback(void *priv) case WIN_VERIFY_ONCE: if (ide->type == IDE_ATAPI) goto abort_cmd; - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; ide->pos=0; ide->atastat = DRDY_STAT | DSC_STAT; @@ -2195,7 +2226,7 @@ ide_callback(void *priv) case WIN_FORMAT: if (ide->type == IDE_ATAPI) goto abort_cmd; - if (ide->cfg_spt == 0) + if (!ide->lba && (ide->cfg_spt == 0)) goto id_not_found; hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); @@ -2315,7 +2346,7 @@ ide_set_handlers(uint8_t board) if (ide_boards[board] == NULL) return; - if (ide_boards[board]->base_main & 0x300) { + if (ide_boards[board]->base_main) { if (ide_boards[board]->bit32) { io_sethandler(ide_boards[board]->base_main, 1, ide_readb, ide_readw, ide_readl, @@ -2332,7 +2363,7 @@ ide_set_handlers(uint8_t board) ide_writeb, NULL, NULL, ide_boards[board]); } - if (ide_boards[board]->side_main & 0x300) { + if (ide_boards[board]->side_main) { io_sethandler(ide_boards[board]->side_main, 1, ide_read_alt_status, NULL, NULL, ide_write_devctl, NULL, NULL, @@ -2347,25 +2378,29 @@ ide_remove_handlers(uint8_t board) if (ide_boards[board] == NULL) return; - if (ide_boards[board]->bit32) { - io_removehandler(ide_boards[board]->base_main, 1, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } else { - io_removehandler(ide_boards[board]->base_main, 1, - ide_readb, ide_readw, NULL, - ide_writeb, ide_writew, NULL, + if (ide_boards[board]->base_main) { + if (ide_boards[board]->bit32) { + io_removehandler(ide_boards[board]->base_main, 1, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } else { + io_removehandler(ide_boards[board]->base_main, 1, + ide_readb, ide_readw, NULL, + ide_writeb, ide_writew, NULL, + ide_boards[board]); + } + io_removehandler(ide_boards[board]->base_main + 1, 7, + ide_readb, NULL, NULL, + ide_writeb, NULL, NULL, + ide_boards[board]); + } + if (ide_boards[board]->side_main) { + io_removehandler(ide_boards[board]->side_main, 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, ide_boards[board]); } - io_removehandler(ide_boards[board]->base_main + 1, 7, - ide_readb, NULL, NULL, - ide_writeb, NULL, NULL, - ide_boards[board]); - io_removehandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); } @@ -2556,10 +2591,8 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_boards[board]->cur_dev = board << 1; if (type & 6) ide_boards[board]->bit32 = 1; - if (base_main != -1) - ide_boards[board]->base_main = base_main; - if (side_main != -1) - ide_boards[board]->side_main = side_main; + ide_boards[board]->base_main = base_main; + ide_boards[board]->side_main = side_main; ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_callback, ide_boards[board], 0); @@ -2607,7 +2640,7 @@ ide_qua_close(void *priv) void * ide_xtide_init(void) { - ide_board_init(0, -1, -1, -1, 0); + ide_board_init(0, -1, 0, 0, 0); return ide_boards[0]; } diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index bf712bcc8..5e2b19e8d 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -10,13 +10,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)hdc_ide_sff8038i.c 1.0.1 2019/10/30 + * Version: @(#)hdc_ide_sff8038i.c 1.0.1 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -25,17 +25,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cdrom/cdrom.h" -#include "../scsi/scsi_device.h" -#include "../scsi/scsi_cdrom.h" -#include "../dma.h" -#include "../io.h" -#include "../device.h" -#include "../keyboard.h" -#include "../mem.h" -#include "../pci.h" -#include "../pic.h" +#include "86box.h" +#include "cdrom.h" +#include "scsi_device.h" +#include "scsi_cdrom.h" +#include "dma.h" +#include "86box_io.h" +#include "device.h" +#include "keyboard.h" +#include "mem.h" +#include "pci.h" +#include "pic.h" #include "hdc.h" #include "hdc_ide.h" #include "hdc_ide_sff8038i.h" @@ -74,21 +74,24 @@ sff_log(const char *fmt, ...) void -sff_bus_master_handlers(sff8038i_t *dev, uint16_t old_base, uint16_t new_base, int enabled) +sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base) { - io_removehandler(old_base, 0x08, - sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, - sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, - dev); + if (dev->base != 0x0000) { + io_removehandler(dev->base, 0x08, + sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, + sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, + dev); + } - if (enabled && new_base) { - io_sethandler(new_base, 0x08, + if (enabled && (base != 0x0000)) { + io_sethandler(base, 0x08, sff_bus_master_read, sff_bus_master_readw, sff_bus_master_readl, sff_bus_master_write, sff_bus_master_writew, sff_bus_master_writel, dev); } dev->enabled = enabled; + dev->base = base; } @@ -370,13 +373,19 @@ sff_bus_master_set_irq(int channel, void *priv) channel &= 0x01; if (dev->status & 0x04) { - if (channel && pci_use_mirq(0)) + sff_log("SFF8038i: Channel %i IRQ raise\n", channel); + if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) pci_set_mirq(0, 0); + else if (dev->irq_mode == 1) + pci_set_irq(dev->slot, dev->irq_pin); else picint(1 << (14 + channel)); } else { - if ((channel & 1) && pci_use_mirq(0)) + sff_log("SFF8038i: Channel %i IRQ lower\n", channel); + if ((dev->irq_mode == 2) && channel && pci_use_mirq(0)) pci_clear_mirq(0, 0); + else if (dev->irq_mode == 1) + pci_clear_irq(dev->slot, dev->irq_pin); else picintc(1 << (14 + channel)); } @@ -412,6 +421,10 @@ sff_reset(void *p) { int i = 0; +#ifdef ENABLE_SFF_LOG + sff_log("SFF8038i: Reset\n"); +#endif + for (i = 0; i < CDROM_NUM; i++) { if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) @@ -422,6 +435,30 @@ sff_reset(void *p) (zip_drives[i].ide_channel < 4) && zip_drives[i].priv) zip_reset((scsi_common_t *) zip_drives[i].priv); } + + sff_bus_master_set_irq(0x00, p); + sff_bus_master_set_irq(0x01, p); +} + + +void +sff_set_slot(sff8038i_t *dev, int slot) +{ + dev->slot = slot; +} + + +void +sff_set_irq_mode(sff8038i_t *dev, int irq_mode) +{ + dev->irq_mode = irq_mode; +} + + +void +sff_set_irq_pin(sff8038i_t *dev, int irq_pin) +{ + dev->irq_pin = irq_pin; } @@ -450,6 +487,10 @@ static void ide_set_bus_master(next_id, sff_bus_master_dma, sff_bus_master_set_irq, dev); + dev->slot = 7; + dev->irq_mode = 2; + dev->irq_pin = PCI_INTA; + next_id++; return dev; diff --git a/src/disk/hdc_ide_sff8038i.h b/src/disk/hdc_ide_sff8038i.h index 0be341eff..bad14a7c6 100644 --- a/src/disk/hdc_ide_sff8038i.h +++ b/src/disk/hdc_ide_sff8038i.h @@ -8,27 +8,30 @@ * * Emulation core dispatcher. * - * Version: @(#)hdc_ide_sff8038i.h 1.0.0 2019/05/12 + * Version: @(#)hdc_ide_sff8038i.h 1.0.2 2020/01/26 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ typedef struct { uint8_t command, status, ptr0, enabled; + uint16_t base, pad; uint32_t ptr, ptr_cur, addr; - int count, eot; + int count, eot, + slot, + irq_mode, irq_pin; } sff8038i_t; extern const device_t sff8038i_device; -extern void sff_bus_master_handlers(sff8038i_t *dev, uint16_t old_base, uint16_t new_base, int enabled); +extern void sff_bus_master_handler(sff8038i_t *dev, int enabled, uint16_t base); extern int sff_bus_master_dma_read(int channel, uint8_t *data, int transfer_length, void *priv); extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_length, void *priv); @@ -36,3 +39,8 @@ extern int sff_bus_master_dma_write(int channel, uint8_t *data, int transfer_len extern void sff_bus_master_set_irq(int channel, void *priv); extern void sff_bus_master_reset(sff8038i_t *dev, uint16_t old_base); + +extern void sff_set_slot(sff8038i_t *dev, int slot); + +extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode); +extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin); diff --git a/src/disk/hdc_st506_at.c b/src/disk/hdc_st506_at.c index 683ade1fc..8f29d4fa4 100644 --- a/src/disk/hdc_st506_at.c +++ b/src/disk/hdc_st506_at.c @@ -30,15 +30,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../pic.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "pic.h" +#include "cpu.h" +#include "machine.h" +#include "timer.h" +#include "plat.h" +#include "ui.h" #include "hdc.h" #include "hdd.h" @@ -463,7 +463,7 @@ mfm_readw(uint16_t port, void *priv) mfm->secount = (mfm->secount - 1) & 0xff; if (mfm->secount) { next_sector(mfm); - mfm->status = STAT_BUSY; + mfm->status = STAT_BUSY | STAT_READY | STAT_DSC; timer_set_delay_u64(&mfm->callback_timer, SECTOR_TIME); } else ui_sb_update_icon(SB_HDD|HDD_BUS_MFM, 0); diff --git a/src/disk/hdc_st506_xt.c b/src/disk/hdc_st506_xt.c index a49e866fe..f096879c6 100644 --- a/src/disk/hdc_st506_xt.c +++ b/src/disk/hdc_st506_xt.c @@ -77,16 +77,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../ui.h" -#include "../plat.h" -#include "../dma.h" -#include "../pic.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "timer.h" +#include "device.h" +#include "ui.h" +#include "plat.h" +#include "dma.h" +#include "pic.h" #include "hdc.h" #include "hdd.h" @@ -1310,6 +1310,13 @@ loadrom(hdc_t *dev, const wchar_t *fn) uint32_t size; FILE *fp; + if (fn == NULL) { +#ifdef ENABLE_ST506_XT_LOG + st506_xt_log("ST506: NULL BIOS ROM file pointer!\n"); +#endif + return; + } + if ((fp = rom_fopen((wchar_t *) fn, L"rb")) == NULL) { st506_xt_log("ST506: BIOS ROM '%ls' not found!\n", fn); return; @@ -1326,7 +1333,8 @@ loadrom(hdc_t *dev, const wchar_t *fn) /* Load the ROM data. */ dev->bios_rom.rom = (uint8_t *)malloc(size); memset(dev->bios_rom.rom, 0xff, size); - (void)fread(dev->bios_rom.rom, size, 1, fp); + if (fread(dev->bios_rom.rom, 1, size, fp) != size) + fatal("ST-506 XT loadrom(): Error reading data\n"); (void)fclose(fp); /* Set up an address mask for this memory. */ diff --git a/src/disk/hdc_xta.c b/src/disk/hdc_xta.c index 9aa8f8faf..9a3d57186 100644 --- a/src/disk/hdc_xta.c +++ b/src/disk/hdc_xta.c @@ -94,16 +94,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" +#include "plat.h" +#include "ui.h" #include "hdc.h" #include "hdd.h" @@ -385,9 +385,6 @@ do_seek(hdc_t *dev, drive_t *drive, int cyl) drive->cur_cyl = (drive->tracks - 1); else drive->cur_cyl = dev->track; - - if (drive->cur_cyl < 0) - drive->cur_cyl = 0; } @@ -628,12 +625,6 @@ do_send: } break; -#if 0 - case CMD_WRITE_VERIFY: - no_data = 1; - /*FALLTHROUGH*/ -#endif - case CMD_WRITE_SECTORS: if (! drive->present) { dev->comp |= COMP_ERR; @@ -666,19 +657,14 @@ do_recv: /* Ready to transfer the data in. */ dev->state = STATE_RDATA; dev->buf_idx = 0; - if (no_data) { - /* Delay a bit, no actual transfer. */ + if (dev->intr & DMA_ENA) { + /* DMA enabled. */ + dev->buf_ptr = dev->sector_buf; xta_set_callback(dev, HDC_TIME); } else { - if (dev->intr & DMA_ENA) { - /* DMA enabled. */ - dev->buf_ptr = dev->sector_buf; - xta_set_callback(dev, HDC_TIME); - } else { - /* No DMA, do PIO. */ - dev->buf_ptr = dev->data; - dev->status |= STAT_REQ; - } + /* No DMA, do PIO. */ + dev->buf_ptr = dev->data; + dev->status |= STAT_REQ; } break; diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 3a6cf6656..26ef50cb8 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -36,11 +36,11 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "hdc.h" #include "hdc_ide.h" @@ -135,7 +135,7 @@ xtide_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_XT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); @@ -162,7 +162,7 @@ xtide_at_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_AT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); @@ -185,7 +185,7 @@ xtide_acculogic_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2, - 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); xtide->ide_board = ide_xtide_init(); @@ -223,7 +223,7 @@ xtide_at_ps2_init(const device_t *info) memset(xtide, 0x00, sizeof(xtide_t)); rom_init(&xtide->bios_rom, ROM_PATH_PS2AT, - 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + 0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); device_add(&ide_isa_2ch_device); diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 97bbf3ddb..6163e8e06 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -20,11 +20,11 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "plat.h" +#include "ui.h" #include "hdd.h" -#include "../cdrom/cdrom.h" +#include "cdrom.h" hard_disk_t hdd[HDD_NUM]; diff --git a/src/disk/hdd_image.c b/src/disk/hdd_image.c index a34f2b5cb..7002c0634 100644 --- a/src/disk/hdd_image.c +++ b/src/disk/hdd_image.c @@ -28,9 +28,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../plat.h" -#include "../random.h" +#include "86box.h" +#include "plat.h" +#include "random.h" #include "hdd.h" @@ -125,12 +125,18 @@ image_is_hdx(const wchar_t *s, int check_signature) f = plat_fopen((wchar_t *)s, L"rb"); if (!f) return 0; - fseeko64(f, 0, SEEK_END); + if (fseeko64(f, 0, SEEK_END)) + fatal("image_is_hdx(): Error while seeking"); filelen = ftello64(f); - fseeko64(f, 0, SEEK_SET); - if (filelen < 44) + if (fseeko64(f, 0, SEEK_SET)) + fatal("image_is_hdx(): Error while seeking"); + if (filelen < 44) { + if (f != NULL) + fclose(f); return 0; - fread(&signature, 1, 8, f); + } + if (fread(&signature, 1, 8, f) != 8) + fatal("image_is_hdx(): Error reading signature\n"); fclose(f); if (signature == 0xD778A82044445459ll) return 1; @@ -163,10 +169,17 @@ image_is_vhd(const wchar_t *s, int check_signature) return 0; fseeko64(f, 0, SEEK_END); filelen = ftello64(f); - fseeko64(f, -512, SEEK_END); - if (filelen < 512) + if (fseeko64(f, -512, SEEK_END) == -1) { + fclose(f); + fatal("image_is_vhd(): Error seeking\n"); + } + if (filelen < 512) { + if (f != NULL) + fclose(f); return 0; - fread(&signature, 1, 8, f); + } + if (fread(&signature, 1, 8, f) != 8) + fatal("image_is_vhd(): Error reading signature\n"); fclose(f); if (signature == 0x78697463656E6F63ll) return 1; @@ -632,13 +645,19 @@ hdd_image_load(int id) } } else { if (image_is_hdi(fn)) { - fseeko64(hdd_images[id].file, 0x8, SEEK_SET); - fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0xC, SEEK_SET); + if (fseeko64(hdd_images[id].file, 0x8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x8\n"); + if (fread(&(hdd_images[id].base), 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading base offset\n"); + if (fseeko64(hdd_images[id].file, 0xC, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offest 0xC\n"); full_size = 0LL; - fread(&full_size, 1, 4, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); + if (fread(&full_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDI: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sector size\n"); if (sector_size != 512) { /* Sector size is not 512 */ hdd_image_log("HDI: Sector size is not 512\n"); @@ -647,19 +666,26 @@ hdd_image_load(int id) memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading number of tracks\n"); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; hdd_images[id].type = 1; } else if (is_hdx[1]) { hdd_images[id].base = 0x28; - fseeko64(hdd_images[id].file, 8, SEEK_SET); - fread(&full_size, 1, 8, hdd_images[id].file); - fseeko64(hdd_images[id].file, 0x10, SEEK_SET); - fread(§or_size, 1, 4, hdd_images[id].file); + if (fseeko64(hdd_images[id].file, 8, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x8\n"); + if (fread(&full_size, 1, 8, hdd_images[id].file) != 8) + fatal("hdd_image_load(): HDX: Error reading full size\n"); + if (fseeko64(hdd_images[id].file, 0x10, SEEK_SET) == -1) + fatal("hdd_image_load(): HDX: Error seeking to offset 0x10\n"); + if (fread(§or_size, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading sector size\n"); if (sector_size != 512) { /* Sector size is not 512 */ hdd_image_log("HDX: Sector size is not 512\n"); @@ -668,16 +694,21 @@ hdd_image_load(int id) memset(hdd[id].fn, 0, sizeof(hdd[id].fn)); return 0; } - fread(&spt, 1, 4, hdd_images[id].file); - fread(&hpc, 1, 4, hdd_images[id].file); - fread(&tracks, 1, 4, hdd_images[id].file); + if (fread(&spt, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading sectors per track\n"); + if (fread(&hpc, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDI: Error reading heads per cylinder\n"); + if (fread(&tracks, 1, 4, hdd_images[id].file) != 4) + fatal("hdd_image_load(): HDX: Error reading number of tracks\n"); hdd[id].spt = spt; hdd[id].hpc = hpc; hdd[id].tracks = tracks; hdd_images[id].type = 2; } else if (is_vhd[1]) { - fseeko64(hdd_images[id].file, -512, SEEK_END); - fread(empty_sector, 1, 512, hdd_images[id].file); + if (fseeko64(hdd_images[id].file, -512, SEEK_END) == -1) + fatal("hdd_image_load(): VHD: Error seeking to 512 bytes before the end of file\n"); + if (fread(empty_sector, 1, 512, hdd_images[id].file) != 512) + fatal("hdd_image_load(): HDX: Error reading the footer\n"); new_vhd_footer(&vft); vhd_footer_from_bytes(vft, (uint8_t *) empty_sector); if (vft->type != 2) { @@ -711,7 +742,8 @@ hdd_image_load(int id) } } - fseeko64(hdd_images[id].file, 0, SEEK_END); + if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) + fatal("hdd_image_load(): Error seeking to the end of file\n"); s = ftello64(hdd_images[id].file); if (s < (full_size + hdd_images[id].base)) ret = prepare_new_hard_disk(id, full_size); @@ -722,7 +754,8 @@ hdd_image_load(int id) } if (is_vhd[0]) { - fseeko64(hdd_images[id].file, 0, SEEK_END); + if (fseeko64(hdd_images[id].file, 0, SEEK_END) == -1) + fatal("hdd_image_load(): VHD: Error seeking to the end of file\n"); s = ftello64(hdd_images[id].file); if (s == (full_size + hdd_images[id].base)) { /* VHD image. */ @@ -741,7 +774,8 @@ hdd_image_seek(uint8_t id, uint32_t sector) addr = (uint64_t)sector << 9LL; hdd_images[id].pos = sector; - fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, addr + hdd_images[id].base, SEEK_SET) == -1) + fatal("hdd_image_seek(): Error seeking\n"); } @@ -750,7 +784,10 @@ hdd_image_read(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { int i; - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Read error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) @@ -792,7 +829,10 @@ hdd_image_write(uint8_t id, uint32_t sector, uint32_t count, uint8_t *buffer) { int i; - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Write error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) @@ -828,7 +868,10 @@ hdd_image_zero(uint8_t id, uint32_t sector, uint32_t count) memset(empty_sector, 0, 512); - fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET); + if (fseeko64(hdd_images[id].file, ((uint64_t)(sector) << 9LL) + hdd_images[id].base, SEEK_SET) == -1) { + fatal("Hard disk image %i: Zero error during seek\n", id); + return; + } for (i = 0; i < count; i++) { if (feof(hdd_images[id].file)) diff --git a/src/disk/hdd_table.c b/src/disk/hdd_table.c index 0ef0829e1..7a68fdb99 100644 --- a/src/disk/hdd_table.c +++ b/src/disk/hdd_table.c @@ -22,7 +22,7 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "hdd.h" diff --git a/src/disk/zip.c b/src/disk/zip.c index 60c775810..429c68dab 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -22,16 +22,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../config.h" -#include "../timer.h" -#include "../device.h" -#include "../piix.h" -#include "../scsi/scsi_device.h" -#include "../nvr.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "timer.h" +#include "config.h" +#include "timer.h" +#include "device.h" +#include "piix.h" +#include "scsi_device.h" +#include "nvr.h" +#include "plat.h" +#include "ui.h" #include "hdc.h" #include "hdc_ide.h" #include "zip.h" @@ -527,9 +527,10 @@ zip_load(zip_t *dev, wchar_t *fn) dev->drv->medium_size = size >> 9; - fseek(dev->drv->f, dev->drv->base, SEEK_SET); + if (fseek(dev->drv->f, dev->drv->base, SEEK_SET) == -1) + fatal("zip_load(): Error seeking to the beginning of the file\n"); - memcpy(dev->drv->image_path, fn, sizeof(dev->drv->image_path)); + wcsncpy(dev->drv->image_path, fn, sizeof_w(dev->drv->image_path)); return 1; } @@ -814,8 +815,14 @@ zip_update_request_length(zip_t *dev, int len, int block_len) /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { case 0x08: + case 0x0a: case 0x28: + case 0x2a: case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + /* Make sure total length is not bigger than sum of the lengths of all the requested blocks. */ bt = (dev->requested_blocks * block_len); @@ -859,14 +866,15 @@ zip_bus_speed(zip_t *dev) { double ret = -1.0; - if (dev->drv->bus_type == ZIP_BUS_SCSI) { + if (dev && dev->drv && (dev->drv->bus_type == ZIP_BUS_SCSI)) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { if (dev && dev->drv) ret = ide_atapi_get_period(dev->drv->ide_channel); if (ret == -1.0) { - dev->callback = -1.0; + if (dev) + dev->callback = -1.0; return 0.0; } else return ret * 1000000.0; @@ -1173,15 +1181,19 @@ zip_blocks(zip_t *dev, int32_t *len, int first_batch, int out) *len = dev->requested_blocks << 9; for (i = 0; i < dev->requested_blocks; i++) { - fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET); + if (fseek(dev->drv->f, dev->drv->base + (dev->sector_pos << 9) + (i << 9), SEEK_SET) == 1) + break; if (feof(dev->drv->f)) break; - if (out) - fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->f); - else - fread(dev->buffer + (i << 9), 1, 512, dev->drv->f); + if (out) { + if (fwrite(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) + fatal("zip_blocks(): Error writing data\n"); + } else { + if (fread(dev->buffer + (i << 9), 1, 512, dev->drv->f) != 512) + fatal("zip_blocks(): Error reading data\n"); + } } zip_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); @@ -1442,6 +1454,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_invalid_field(dev); return; } + /*FALLTHROUGH*/ case GPCMD_SCSI_RESERVE: case GPCMD_SCSI_RELEASE: case GPCMD_TEST_UNIT_READY: @@ -2123,8 +2136,10 @@ zip_phase_data_out(scsi_common_t *sc) dev->buffer[6] = (s >> 8) & 0xff; dev->buffer[7] = s & 0xff; } - fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET); - fwrite(dev->buffer, 1, 512, dev->drv->f); + if (fseek(dev->drv->f, dev->drv->base + (i << 9), SEEK_SET) == -1) + fatal("zip_phase_data_out(): Error seeking\n"); + if (fwrite(dev->buffer, 1, 512, dev->drv->f) != 512) + fatal("zip_phase_data_out(): Error writing data\n"); } break; case GPCMD_MODE_SELECT_6: @@ -2367,7 +2382,7 @@ zip_hard_reset(void) zip_log("ZIP hard_reset drive=%d\n", c); /* Make sure to ignore any SCSI ZIP drive that has an out of range ID. */ - if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id > SCSI_ID_MAX)) + if ((zip_drives[c].bus_type == ZIP_BUS_SCSI) && (zip_drives[c].scsi_device_id >= SCSI_ID_MAX)) continue; /* Make sure to ignore any ATAPI ZIP drive that has an out of range IDE channel. */ diff --git a/src/dma.c b/src/dma.c index 7322f471e..802c0e836 100644 --- a/src/dma.c +++ b/src/dma.c @@ -8,36 +8,32 @@ * * Implementation of the Intel DMA controllers. * - * Version: @(#)dma.c 1.0.7 2019/09/28 + * Version: @(#)dma.c 1.0.9 2020/01/26 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include #include #include #include "86box.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 "cpu_common/cpu.h" +#include "cpu_common/x86.h" #include "machine/machine.h" #include "mca.h" #include "mem.h" -#include "io.h" +#include "86box_io.h" #include "dma.h" dma_t dma[8]; +uint8_t dma_e; static uint8_t dmaregs[16]; @@ -615,6 +611,8 @@ dma_reset(void) dma_wp = dma16_wp = 0; dma_m = 0; + dma_e = 0xff; + for (c = 0; c < 16; c++) dmaregs[c] = dma16regs[c] = 0; for (c = 0; c < 8; c++) { @@ -669,6 +667,20 @@ dma_alias_set(void) } +void +dma_alias_set_piix(void) +{ + io_sethandler(0x0090, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_sethandler(0x0094, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_sethandler(0x0098, 1, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); + io_sethandler(0x009C, 3, + dma_page_read,NULL,NULL, dma_page_write,NULL,NULL, NULL); +} + + void dma_alias_remove(void) { @@ -736,6 +748,8 @@ dma_channel_read(int channel) return(DMA_NODATA); } + if (!(dma_e & (1 << channel))) + return(DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) return(DMA_NODATA); if ((dma_c->mode & 0xC) != 8) @@ -809,6 +823,8 @@ dma_channel_write(int channel, uint16_t val) return(DMA_NODATA); } + if (!(dma_e & (1 << channel))) + return(DMA_NODATA); if ((dma_m & (1 << channel)) && !dma_req_is_soft) return(DMA_NODATA); if ((dma_c->mode & 0xC) != 4) diff --git a/src/dma.h b/src/dma.h index 75f923e66..7761107f1 100644 --- a/src/dma.h +++ b/src/dma.h @@ -8,15 +8,15 @@ * * Definitions for the Intel DMA controller. * - * Version: @(#)dma.h 1.0.2 2018/03/12 + * Version: @(#)dma.h 1.0.4 2020/01/26 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * 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 @@ -63,6 +63,7 @@ typedef struct { extern dma_t dma[8]; +extern uint8_t dma_e; extern void dma_init(void); @@ -85,6 +86,7 @@ extern int dma_channel_read(int channel); extern int dma_channel_write(int channel, uint16_t val); extern void dma_alias_set(void); +extern void dma_alias_set_piix(void); extern void dma_alias_remove(void); extern void dma_alias_remove_piix(void); diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 401093ef0..d4eebc796 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -9,13 +9,13 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.c 1.0.21 2019/10/20 + * Version: @(#)fdc.c 1.0.22 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -24,15 +24,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../timer.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "cpu.h" +#include "machine.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "timer.h" +#include "ui.h" #include "fdd.h" #include "fdc.h" @@ -702,10 +702,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->stat = 0x00; fdc->pnum = fdc->ptot = 0; } - if (val&4) { - fdc->stat = 0x80; - fdc->pnum = fdc->ptot = 0; - } if ((val&4) && !(fdc->dor&4)) { timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); fdc->interrupt = -1; @@ -775,7 +771,16 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->stat |= 0x10; fdc_log("Starting FDC command %02X\n",fdc->command); - switch (fdc->command & 0x1f) { + if (((fdc->command & 0x1f) == 0x02) || ((fdc->command & 0x1f) == 0x05) || + ((fdc->command & 0x1f) == 0x06) || ((fdc->command & 0x1f) == 0x0a) || + ((fdc->command & 0x1f) == 0x0c) || ((fdc->command & 0x1f) == 0x0d) || + ((fdc->command & 0x1f) == 0x11) || ((fdc->command & 0x1f) == 0x16) || + ((fdc->command & 0x1f) == 0x19) || ((fdc->command & 0x1f) == 0x1d)) + fdc->processed_cmd = fdc->command & 0x1f; + else + fdc->processed_cmd = fdc->command; + + switch (fdc->processed_cmd) { case 0x01: /*Mode*/ if (fdc->flags & FDC_FLAG_NSC) { fdc->pnum = 0; @@ -921,7 +926,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) } if (fdc->pnum == fdc->ptot) { fdc_log("Got all params %02X\n", fdc->command); - fdc->interrupt = fdc->command & 0x1F; + fdc->interrupt = fdc->processed_cmd; fdc->reset_stat = 0; /* Disable timer if enabled. */ timer_disable(&fdc->timer); @@ -950,7 +955,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) break; } /* Process the firt phase of the command. */ - switch (fdc->interrupt & 0x1F) { + switch (fdc->processed_cmd) { case 0x02: /* Read a track */ fdc_io_command_phase1(fdc, 0); fdc->read_track_sector.id.c = fdc->params[1]; @@ -994,6 +999,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) case 0x16: /* Verify */ if (fdc->params[0] & 0x80) fdc->sc = fdc->params[7]; + /*FALLTHROUGH*/ case 0x06: /* Read data */ case 0x0c: /* Read deleted data */ fdc_io_command_phase1(fdc, 0); @@ -1071,7 +1077,8 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->stat = (1 << fdc->drive); if (!(fdc->flags & FDC_FLAG_PCJR)) fdc->stat |= 0x80; - fdc->head = (fdc->params[0] & 4) ? 1 : 0; + /* fdc->head = (fdc->params[0] & 4) ? 1 : 0; */ + fdc->head = 0; /* TODO: See if this is correct. */ fdc->st0 = fdc->params[0] & 0x03; fdc->st0 |= (fdc->params[0] & 4); fdc->st0 |= 0x80; @@ -1209,21 +1216,22 @@ fdc_read(uint16_t addr, void *priv) } } else { if (is486 || !fdc->enable_3f1) - return 0xff; + ret = 0xff; + else { + ret = 0x70; - ret = 0x70; + drive = real_drive(fdc, fdc->dor & 3); - drive = real_drive(fdc, fdc->dor & 3); + if (drive) + ret &= ~0x40; + else + ret &= ~0x20; - if (drive) - ret &= ~0x40; - else - ret &= ~0x20; - - if (fdc->dor & 0x10) - ret |= 1; - if (fdc->dor & 0x20) - ret |= 2; + if (fdc->dor & 0x10) + ret |= 1; + if (fdc->dor & 0x20) + ret |= 2; + } } break; case 2: @@ -1993,6 +2001,13 @@ fdc_set_swap(fdc_t *fdc, uint8_t swap) } +void +fdc_set_irq(fdc_t *fdc, int irq) +{ + fdc->irq = irq; +} + + void fdc_set_base(fdc_t *fdc, int base) { diff --git a/src/floppy/fdc.h b/src/floppy/fdc.h index c6c3a90bf..4fae14c62 100644 --- a/src/floppy/fdc.h +++ b/src/floppy/fdc.h @@ -9,15 +9,15 @@ * Implementation of the NEC uPD-765 and compatible floppy disk * controller. * - * Version: @(#)fdc.h 1.0.8 2019/10/20 + * Version: @(#)fdc.h 1.0.9 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2018,2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2018-2020 Fred N. van Kempen. */ #ifndef EMU_FDC_H # define EMU_FDC_H @@ -36,7 +36,7 @@ typedef struct { - uint8_t dor, stat, command, dat, st0, swap; + uint8_t dor, stat, command, processed_cmd, dat, st0, swap; uint8_t swwp, disable_write; uint8_t params[256], res[256]; uint8_t specify[256], format_dat[256]; @@ -154,6 +154,7 @@ extern int fdc_is_verify(fdc_t *fdc); extern void fdc_overrun(fdc_t *fdc); extern void fdc_set_base(fdc_t *fdc, int base); +extern void fdc_set_irq(fdc_t *fdc, int irq); extern int fdc_getdata(fdc_t *fdc, int last); extern int fdc_data(fdc_t *fdc, uint8_t data); diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 92bffd9be..37f100002 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -24,10 +24,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" +#include "ui.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_fdi.h" @@ -491,7 +491,8 @@ fdd_load(int drive, wchar_t *fn) f = plat_fopen(fn, L"rb"); if (!f) return; - fseek(f, -1, SEEK_END); + if (fseek(f, -1, SEEK_END) == -1) + fatal("fdd_load(): Error seeking to the end of the file\n"); size = ftell(f) + 1; fclose(f); while (loaders[c].ext) { diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index 4fb68c606..8eb4d0f42 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -26,13 +26,13 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../dma.h" -#include "../nvr.h" -#include "../random.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "timer.h" +#include "dma.h" +#include "nvr.h" +#include "random.h" +#include "plat.h" +#include "ui.h" #include "fdd.h" #include "fdc.h" #include "fdd_86f.h" @@ -826,7 +826,7 @@ d86f_byteperiod(int drive) int d86f_is_mfm(int drive) { - return (d86f_track_flags(drive) & 8) ? 1 : 0; + return ((d86f_track_flags(drive) & 0x18) == 0x08) ? 1 : 0; } @@ -1174,15 +1174,8 @@ d86f_put_bit(int drive, int side, int bit) if (d86f_has_surface_desc(drive)) { surface_bit = (surface_data >> track_bit) & 1; if (! surface_bit) { - if (! current_bit) { - /* Bit is 0 and is not set to fuzzy, we overwrite it as is. */ - dev->last_word[side] |= bit; - current_bit = bit; - } else { - /* Bit is 1 and is not set to fuzzy, we overwrite it as is. */ - dev->last_word[side] |= bit; - current_bit = bit; - } + dev->last_word[side] |= bit; + current_bit = bit; } else { if (current_bit) { /* Bit is 1 and is set to fuzzy, we overwrite it with a non-fuzzy bit. */ @@ -2949,10 +2942,13 @@ d86f_read_track(int drive, int track, int thin_track, int side, uint16_t *da, ui if (dev->track_offset[logical_track]) { if (! thin_track) { - fseek(dev->f, dev->track_offset[logical_track], SEEK_SET); - fread(&(dev->side_flags[side]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[logical_track], SEEK_SET) == -1) + fatal("d86f_read_track(): Error seeking to offset dev->track_offset[logical_track]\n"); + if (fread(&(dev->side_flags[side]), 1, 2, dev->f) != 2) + fatal("d86f_read_track(): Error reading side flags\n"); if (d86f_has_extra_bit_cells(drive)) { - fread(&(dev->extra_bit_cells[side]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[side]), 1, 4, dev->f) != 4) + fatal("d86f_read_track(): Error reading number of extra bit cells\n"); /* If RPM shift is 0% and direction is 1, do not adjust extra bit cells, as that is the whole track length. */ if (d86f_get_rpm_mode(drive) || !d86f_get_speed_shift_dir(drive)) { @@ -3146,7 +3142,8 @@ d86f_write_tracks(int drive, FILE **f, uint32_t *track_table) } if (tbl[logical_track]) { - fseek(*f, tbl[logical_track], SEEK_SET); + if (fseek(*f, tbl[logical_track], SEEK_SET) == -1) + fatal("d86f_write_tracks(): Error seeking to offset tbl[logical_track]\n"); d86f_write_track(drive, f, side, d86f_handler[drive].encoded_data(drive, side), dev->track_surface_data[side]); } } @@ -3161,7 +3158,7 @@ d86f_writeback(int drive) { d86f_t *dev = d86f[drive]; uint8_t header[32]; - int header_size; + int header_size, size; #ifdef D86F_COMPRESS uint32_t len; int ret = 0; @@ -3172,11 +3169,16 @@ d86f_writeback(int drive) if (! dev->f) return; /* First write the track offsets table. */ - fseek(dev->f, 0, SEEK_SET); - fread(header, 1, header_size, dev->f); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking to the beginning of the file\n"); + if (fread(header, 1, header_size, dev->f) != header_size) + fatal("86F write_back(): Error reading header size\n"); - fseek(dev->f, 8, SEEK_SET); - fwrite(dev->track_offset, 1, d86f_get_track_table_size(drive), dev->f); + if (fseek(dev->f, 8, SEEK_SET) == -1) + fatal("86F write_back(): Error seeking\n"); + size = d86f_get_track_table_size(drive); + if (fwrite(dev->track_offset, 1, size, dev->f) != size) + fatal("86F write_back(): Error writing data\n"); d86f_write_tracks(drive, &dev->f, NULL); @@ -3586,7 +3588,9 @@ d86f_load(int drive, wchar_t *fn) return; } - fread(&(dev->version), 2, 1, dev->f); + if (fread(&(dev->version), 1, 2, dev->f) != 2) + fatal("d86f_load(): Error reading format version\n"); + if (dev->version != D86FVER) { /* File is not of a recognized format version, abort. */ if (dev->version == 0x0063) { @@ -3779,10 +3783,13 @@ d86f_load(int drive, wchar_t *fn) } /* Load track 0 flags as default. */ - fseek(dev->f, dev->track_offset[0], SEEK_SET); - fread(&(dev->side_flags[0]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[0], SEEK_SET) == -1) + fatal("d86f_load(): Track 0: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[0]), 1, 2, dev->f) != 2) + fatal("d86f_load(): Track 0: Error reading side flags\n"); if (dev->disk_flags & 0x80) { - fread(&(dev->extra_bit_cells[0]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[0]), 1, 4, dev->f) != 4) + fatal("d86f_load(): Track 0: Error reading the amount of extra bit cells\n"); if ((dev->disk_flags & 0x1060) != 0x1000) { if (dev->extra_bit_cells[0] < -32768) dev->extra_bit_cells[0] = -32768; if (dev->extra_bit_cells[0] > 32768) dev->extra_bit_cells[0] = 32768; @@ -3792,10 +3799,13 @@ d86f_load(int drive, wchar_t *fn) } if (d86f_get_sides(drive) == 2) { - fseek(dev->f, dev->track_offset[1], SEEK_SET); - fread(&(dev->side_flags[1]), 2, 1, dev->f); + if (fseek(dev->f, dev->track_offset[1], SEEK_SET) == -1) + fatal("d86f_load(): Track 1: Error seeking to the beginning of the file\n"); + if (fread(&(dev->side_flags[1]), 1, 2, dev->f) != 2) + fatal("d86f_load(): Track 1: Error reading side flags\n"); if (dev->disk_flags & 0x80) { - fread(&(dev->extra_bit_cells[1]), 4, 1, dev->f); + if (fread(&(dev->extra_bit_cells[1]), 1, 4, dev->f) != 4) + fatal("d86f_load(): Track 4: Error reading the amount of extra bit cells\n"); if ((dev->disk_flags & 0x1060) != 0x1000) { if (dev->extra_bit_cells[1] < -32768) dev->extra_bit_cells[1] = -32768; if (dev->extra_bit_cells[1] > 32768) dev->extra_bit_cells[1] = 32768; diff --git a/src/floppy/fdd_common.c b/src/floppy/fdd_common.c index 3b3bfa338..3ad3db4aa 100644 --- a/src/floppy/fdd_common.c +++ b/src/floppy/fdd_common.c @@ -19,8 +19,8 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" +#include "86box.h" +#include "timer.h" #include "fdd.h" #include "fdd_common.h" diff --git a/src/floppy/fdd_fdi.c b/src/floppy/fdd_fdi.c index d49c851a5..04315377a 100644 --- a/src/floppy/fdd_fdi.c +++ b/src/floppy/fdd_fdi.c @@ -26,9 +26,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_img.h" @@ -329,19 +329,21 @@ fdi_load(int drive, wchar_t *fn) /* Allocate a drive block. */ dev = (fdi_t *)malloc(sizeof(fdi_t)); - memset(dev, 0x00, sizeof(fdi_t)); - dev->f = plat_fopen(fn, L"rb"); if (dev == NULL) { - free(dev); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); return; } + memset(dev, 0x00, sizeof(fdi_t)); + d86f_unregister(drive); - fread(header, 1, 25, dev->f); - fseek(dev->f, 0, SEEK_SET); + dev->f = plat_fopen(fn, L"rb"); + if (fread(header, 1, 25, dev->f) != 25) + fatal("fdi_load(): Error reading header\n"); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("fdi_load(): Error seeking to the beginning of the file\n"); header[25] = 0; if (strcmp(header, "Formatted Disk Image file") != 0) { /* This is a Japanese FDI file. */ diff --git a/src/floppy/fdd_imd.c b/src/floppy/fdd_imd.c index 421e339cf..14078ee01 100644 --- a/src/floppy/fdd_imd.c +++ b/src/floppy/fdd_imd.c @@ -23,9 +23,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_imd.h" @@ -190,8 +190,8 @@ track_is_xdf(int drive, int side, int track) dev->current_side_flags[side] = (dev->tracks[track][side].params[3] == 19) ? 0x08 : 0x28; return((dev->tracks[track][side].params[3] == 19) ? 2 : 1); } - return(0); } + return(0); } else { if (dev->tracks[track][side].params[4] != 0xFF) return(0); @@ -629,6 +629,7 @@ imd_load(int drive, wchar_t *fn) dev->f = plat_fopen(fn, L"rb"); if (dev->f == NULL) { memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + free(dev); return; } writeprot[drive] = 1; @@ -638,8 +639,10 @@ imd_load(int drive, wchar_t *fn) writeprot[drive] = 1; fwriteprot[drive] = writeprot[drive]; - fseek(dev->f, 0, SEEK_SET); - fread(&magic, 1, 4, dev->f); + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file\n"); + if (fread(&magic, 1, 4, dev->f) != 4) + fatal("imd_load(): Error reading the magic number\n"); if (magic != 0x20444D49) { imd_log("IMD: Not a valid ImageDisk image\n"); fclose(dev->f); @@ -649,14 +652,24 @@ imd_load(int drive, wchar_t *fn) } else imd_log("IMD: Valid ImageDisk image\n"); - fseek(dev->f, 0, SEEK_END); + if (fseek(dev->f, 0, SEEK_END) == -1) + fatal("imd_load(): Error seeking to the end of the file\n"); fsize = ftell(dev->f); - fseek(dev->f, 0, SEEK_SET); + if (fsize <= 0) { + imd_log("IMD: Too small ImageDisk image\n"); + fclose(dev->f); + free(dev); + memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); + return; + } + if (fseek(dev->f, 0, SEEK_SET) == -1) + fatal("imd_load(): Error seeking to the beginning of the file again\n"); dev->buffer = malloc(fsize); - fread(dev->buffer, 1, fsize, dev->f); + if (fread(dev->buffer, 1, fsize, dev->f) != fsize) + fatal("imd_load(): Error reading data\n"); buffer = dev->buffer; - buffer2 = strchr(buffer, 0x1A); + buffer2 = memchr(buffer, 0x1A, fsize); if (buffer2 == NULL) { imd_log("IMD: No ASCII EOF character\n"); fclose(dev->f); diff --git a/src/floppy/fdd_img.c b/src/floppy/fdd_img.c index 5e0bfaacd..54039a320 100644 --- a/src/floppy/fdd_img.c +++ b/src/floppy/fdd_img.c @@ -30,10 +30,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../config.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "config.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_img.h" @@ -393,15 +393,19 @@ write_back(int drive) { img_t *dev = img[drive]; int ssize = 128 << ((int) dev->sector_size); - int side; + int side, size; if (dev->f == NULL) return; if (dev->disk_at_once) return; - fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET); - for (side = 0; side < dev->sides; side++) - fwrite(dev->track_data[side], dev->sectors * ssize, 1, dev->f); + if (fseek(dev->f, dev->base + (dev->track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + pclog("IMG write_back(): Error seeking to the beginning of the file\n"); + for (side = 0; side < dev->sides; side++) { + size = dev->sectors * ssize; + if (fwrite(dev->track_data[side], 1, size, dev->f) != size) + fatal("IMG write_back(): Error writing data\n"); + } } @@ -486,8 +490,10 @@ img_seek(int drive, int track) is_t0 = (track == 0) ? 1 : 0; - if (! dev->disk_at_once) - fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET); + if (! dev->disk_at_once) { + if (fseek(dev->f, dev->base + (track * dev->sectors * ssize * dev->sides), SEEK_SET) == -1) + fatal("img_seek(): Error seeking\n"); + } for (side = 0; side < dev->sides; side++) { if (dev->disk_at_once) { @@ -1103,7 +1109,8 @@ jump_if_fdf: /* The BPB readings appear to be valid, so let's set the values. */ if (fdi) { /* The image is a Japanese FDI, therefore we read the number of tracks from the header. */ - fseek(dev->f, 0x1C, SEEK_SET); + if (fseek(dev->f, 0x1C, SEEK_SET) == -1) + fatal("Japanese FDI: Failed when seeking to 0x1C\n"); fread(&(dev->tracks), 1, 4, dev->f); } else { if (!cqm && !fdf) { @@ -1155,8 +1162,12 @@ jump_if_fdf: dev->gap2_size = (temp_rate == 3) ? 41 : 22; if (dev->dmf) dev->gap3_size = 8; - else - dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + else { + if (dev->sectors == -1) + dev->gap3_size = 8; + else + dev->gap3_size = gap3_sizes[temp_rate][dev->sector_size][dev->sectors]; + } if (! dev->gap3_size) { img_log("ERROR: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41); fclose(dev->f); diff --git a/src/floppy/fdd_json.c b/src/floppy/fdd_json.c index d194b811d..9b96f0c3b 100644 --- a/src/floppy/fdd_json.c +++ b/src/floppy/fdd_json.c @@ -51,9 +51,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdc.h" @@ -395,7 +395,6 @@ json_seek(int drive, int track) int side, sector; int rate, gap2, gap3, pos; int ssize, rsec, asec; - int interleave_type; if (dev->f == NULL) { json_log("JSON: seek: no file loaded!\n"); @@ -415,8 +414,6 @@ json_seek(int drive, int track) d86f_reset_index_hole_pos(drive, 1); d86f_destroy_linked_lists(drive, 1); - interleave_type = 0; - if (track > dev->tracks) { d86f_zero_track(drive); return; @@ -438,13 +435,9 @@ json_seek(int drive, int track) pos = d86f_prepare_pretrack(drive, side, 0); for (sector=0; sectorspt[track][side]; sector++) { - if (interleave_type == 0) { - rsec = dev->sects[track][side][sector].sector; - asec = sector; - } else { - rsec = fdd_dmf_r[sector]; - asec = dev->interleave_ordered[rsec][side]; - } + rsec = dev->sects[track][side][sector].sector; + asec = sector; + id[0] = track; id[1] = side; id[2] = rsec; diff --git a/src/floppy/fdd_mfm.c b/src/floppy/fdd_mfm.c index 879bc200e..13d9e88a0 100644 --- a/src/floppy/fdd_mfm.c +++ b/src/floppy/fdd_mfm.c @@ -22,9 +22,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_img.h" @@ -338,7 +338,7 @@ mfm_read_side(int drive, int side) { mfm_t *dev = mfm[drive]; int track_index, track_size; - int track_bytes; + int track_bytes, ret; if (dev->hdr.if_type & 0x80) track_index = get_adv_track_index(drive, side, dev->cur_track); @@ -354,10 +354,13 @@ mfm_read_side(int drive, int side) memset(dev->track_data[side], 0x00, track_bytes); else { if (dev->hdr.if_type & 0x80) - fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); + ret = fseek(dev->f, dev->adv_tracks[track_index].track_offset, SEEK_SET); else - fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); - fread(dev->track_data[side], 1, track_bytes, dev->f); + ret = fseek(dev->f, dev->tracks[track_index].track_offset, SEEK_SET); + if (ret == -1) + fatal("mfm_read_side(): Error seeking to the beginning of the file\n"); + if (fread(dev->track_data[side], 1, track_bytes, dev->f) != track_bytes) + fatal("mfm_read_side(): Error reading track bytes\n"); } mfm_log("drive = %i, side = %i, dev->cur_track = %i, track_index = %i, track_size = %i\n", @@ -399,7 +402,7 @@ mfm_load(int drive, wchar_t *fn) { mfm_t *dev; double dbr; - int i; + int i, size; writeprot[drive] = fwriteprot[drive] = 1; @@ -417,16 +420,22 @@ mfm_load(int drive, wchar_t *fn) d86f_unregister(drive); /* Read the header. */ - fread(&dev->hdr, 1, sizeof(mfm_header_t), dev->f); + size = sizeof(mfm_header_t); + if (fread(&dev->hdr, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading header\n"); /* Calculate tracks * sides, allocate the tracks array, and read it. */ dev->total_tracks = dev->hdr.tracks_no * dev->hdr.sides_no; if (dev->hdr.if_type & 0x80) { dev->adv_tracks = (mfm_adv_track_t *) malloc(dev->total_tracks * sizeof(mfm_adv_track_t)); - fread(dev->adv_tracks, 1, dev->total_tracks * sizeof(mfm_adv_track_t), dev->f); + size = dev->total_tracks * sizeof(mfm_adv_track_t); + if (fread(dev->adv_tracks, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading advanced tracks\n"); } else { dev->tracks = (mfm_track_t *) malloc(dev->total_tracks * sizeof(mfm_track_t)); - fread(dev->tracks, 1, dev->total_tracks * sizeof(mfm_track_t), dev->f); + size = dev->total_tracks * sizeof(mfm_track_t); + if (fread(dev->tracks, 1, size, dev->f) != size) + fatal("mfm_load(): Error reading tracks\n"); } /* The chances of finding a HxC MFM image of a single-sided thin track diff --git a/src/floppy/fdd_td0.c b/src/floppy/fdd_td0.c index fd4d4419f..b7517f437 100644 --- a/src/floppy/fdd_td0.c +++ b/src/floppy/fdd_td0.c @@ -35,9 +35,9 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "plat.h" #include "fdd.h" #include "fdd_86f.h" #include "fdd_td0.h" @@ -231,8 +231,10 @@ fdd_image_read(int drive, char *buffer, uint32_t offset, uint32_t len) { td0_t *dev = td0[drive]; - fseek(dev->f, offset, SEEK_SET); - fread(buffer, 1, len, dev->f); + if (fseek(dev->f, offset, SEEK_SET) == -1) + fatal("fdd_image_read(): Error seeking to the beginning of the file\n"); + if (fread(buffer, 1, len, dev->f) != len) + fatal("fdd_image_read(): Error reading data\n"); } @@ -260,8 +262,10 @@ state_data_read(td0dsk_t *state, uint8_t *buf, uint16_t size) image_size = ftell(state->fdd_file); if (size > image_size - state->fdd_file_offset) size = (image_size - state->fdd_file_offset) & 0xffff; - fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET); - fread(buf, 1, size, state->fdd_file); + if (fseek(state->fdd_file, state->fdd_file_offset, SEEK_SET) == -1) + fatal("TD0: Failed to seek in state_data_read()\n"); + if (fread(buf, 1, size, state->fdd_file) != size) + fatal("TD0: Error reading data in state_data_read()\n"); state->fdd_file_offset += size; return(size); @@ -652,8 +656,10 @@ td0_initialize(int drive) state_Decode(&disk_decode, dev->imagebuf, TD0_MAX_BUFSZ); } else { td0_log("TD0: File is uncompressed\n"); - fseek(dev->f, 12, SEEK_SET); - fread(dev->imagebuf, 1, file_size - 12, dev->f); + if (fseek(dev->f, 12, SEEK_SET) == -1) + fatal("td0_initialize(): Error seeking to offet 12\n"); + if (fread(dev->imagebuf, 1, file_size - 12, dev->f) != (file_size - 12)) + fatal("td0_initialize(): Error reading image buffer\n"); } if (header[7] & 0x80) @@ -904,15 +910,15 @@ static void set_sector(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n) { td0_t *dev = td0[drive]; - int i = 0; + int i = 0, cyl = c; dev->current_sector_index[side] = 0; - if (c != dev->track) return; - for (i = 0; i < dev->track_spt[c][side]; i++) { - if ((dev->sects[c][side][i].track == c) && - (dev->sects[c][side][i].head == h) && - (dev->sects[c][side][i].sector == r) && - (dev->sects[c][side][i].size == n)) { + if (cyl != dev->track) return; + for (i = 0; i < dev->track_spt[cyl][side]; i++) { + if ((dev->sects[cyl][side][i].track == c) && + (dev->sects[cyl][side][i].head == h) && + (dev->sects[cyl][side][i].sector == r) && + (dev->sects[cyl][side][i].size == n)) { dev->current_sector_index[side] = i; } } diff --git a/src/floppy/fdi2raw.c b/src/floppy/fdi2raw.c index b42ca2f1d..bf54babfb 100644 --- a/src/floppy/fdi2raw.c +++ b/src/floppy/fdi2raw.c @@ -37,7 +37,7 @@ /* ELSE */ #define xmalloc malloc #define HAVE_STDARG_H -#include "../86box.h" +#include "86box.h" #include "fdi2raw.h" @@ -187,10 +187,14 @@ static uae_u8 temp, temp2; static uae_u8 *expand_tree (uae_u8 *stream, NODE *node) { if (temp & temp2) { - fdi_free (node->left); - node->left = 0; - fdi_free (node->right); - node->right = 0; + if (node->left) { + fdi_free (node->left); + node->left = 0; + } + if (node->right) { + fdi_free (node->right); + node->right = 0; + } temp2 >>= 1; if (!temp2) { temp = *stream++; @@ -322,7 +326,9 @@ static void fdi_decode (uae_u8 *stream, int size, uae_u8 *out) ((uae_u32*)out)[i] = v; } free_nodes (root.left); + root.left = 0; free_nodes (root.right); + root.right = 0; } } @@ -2029,9 +2035,16 @@ FDI *fdi2raw_header(FILE *f) memset (fdi, 0, sizeof (FDI)); fdi->file = f; oldseek = ftell (fdi->file); - fseek (fdi->file, 0, SEEK_SET); - fread (fdi->header, 2048, 1, fdi->file); - fseek (fdi->file, oldseek, SEEK_SET); + if (oldseek == -1) { + fdi_free(fdi); + return NULL; + } + if (fseek (fdi->file, 0, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to the beginning of the file\n"); + if (fread (fdi->header, 1, 2048, fdi->file) != 2048) + fatal("fdi2raw_header(): Error reading header\n"); + if (fseek (fdi->file, oldseek, SEEK_SET) == -1) + fatal("fdi2raw_header(): Error seeking to offset oldseek\n"); if (memcmp (fdiid, fdi->header, strlen ((char *)fdiid)) ) { fdi_free(fdi); return NULL; @@ -2127,8 +2140,10 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac fdi->err = 0; fdi->track_src_len = fdi->track_offsets[track + 1] - fdi->track_offsets[track]; - fseek (fdi->file, fdi->track_offsets[track], SEEK_SET); - fread (fdi->track_src_buffer, fdi->track_src_len, 1, fdi->file); + if (fseek (fdi->file, fdi->track_offsets[track], SEEK_SET) == -1) + fatal("fdi2raw_loadtrack(): Error seeking to the beginning of the file\n"); + if (fread (fdi->track_src_buffer, 1, fdi->track_src_len, fdi->file) != fdi->track_src_len) + fatal("fdi2raw_loadtrack(): Error reading data\n"); memset (fdi->track_dst_buffer, 0, MAX_DST_BUFFER); fdi->track_dst_buffer_timing[0] = 0; @@ -2167,7 +2182,7 @@ int fdi2raw_loadtrack (FDI *fdi, uae_u16 *mfmbuf, uae_u16 *tracktiming, int trac zxx (fdi); outlen = -1; - } else if (fdi->track_type < 0x10) { + } else if (fdi->track_type < 0x0f) { decode_normal_track[fdi->track_type](fdi); fix_mfm_sync (fdi); diff --git a/src/game/gameport.c b/src/game/gameport.c index eb3eaf893..f2c545a26 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -39,12 +39,12 @@ #include #include #include -#include "../86box.h" -#include "../machine/machine.h" -#include "../cpu/cpu.h" -#include "../device.h" -#include "../io.h" -#include "../timer.h" +#include "86box.h" +#include "machine.h" +#include "cpu.h" +#include "device.h" +#include "86box_io.h" +#include "timer.h" #include "gameport.h" #include "joystick_ch_flightstick_pro.h" #include "joystick_standard.h" @@ -90,6 +90,7 @@ static const joystick_if_t *joystick_list[] = { &joystick_standard_4button, &joystick_standard_6button, &joystick_standard_8button, + &joystick_4axis_4button, &joystick_ch_flightstick_pro, &joystick_sw_pad, &joystick_tm_fcs, @@ -265,7 +266,7 @@ gameport_init(const device_t *info) { gameport_t *p = NULL; - if (joystick_type == 7) { + if (joystick_type == JOYSTICK_TYPE_NONE) { p = NULL; return(p); } @@ -284,7 +285,7 @@ gameport_201_init(const device_t *info) { gameport_t *p; - if (joystick_type == 7) { + if (joystick_type == JOYSTICK_TYPE_NONE) { p = NULL; return(p); } diff --git a/src/game/gameport.h b/src/game/gameport.h index e1fec8fb8..0ef53921d 100644 --- a/src/game/gameport.h +++ b/src/game/gameport.h @@ -45,8 +45,10 @@ #define POV_X 0x80000000 #define POV_Y 0x40000000 +#define SLIDER 0x20000000 #define AXIS_NOT_PRESENT -99999 +#define JOYSTICK_TYPE_NONE 8 #define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) @@ -57,6 +59,7 @@ typedef struct { int a[8]; int b[32]; int p[4]; + int s[2]; struct { char name[260]; @@ -73,9 +76,16 @@ typedef struct { int id; } pov[4]; + struct + { + char name[260]; + int id; + } slider[2]; + int nr_axes; int nr_buttons; int nr_povs; + int nr_sliders; } plat_joystick_t; typedef struct { diff --git a/src/game/joystick_ch_flightstick_pro.c b/src/game/joystick_ch_flightstick_pro.c index 062e753a6..5b7b99da8 100644 --- a/src/game/joystick_ch_flightstick_pro.c +++ b/src/game/joystick_ch_flightstick_pro.c @@ -39,9 +39,9 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "timer.h" #include "gameport.h" #include "joystick_standard.h" diff --git a/src/game/joystick_standard.c b/src/game/joystick_standard.c index f05634a9b..29b31f590 100644 --- a/src/game/joystick_standard.c +++ b/src/game/joystick_standard.c @@ -39,9 +39,9 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "timer.h" #include "gameport.h" #include "joystick_standard.h" @@ -144,6 +144,27 @@ static int joystick_standard_read_axis_4button(void *p, int axis) return 0; } } + +static int joystick_standard_read_axis_4axis(void *p, int axis) +{ + if (!JOYSTICK_PRESENT(0)) + return AXIS_NOT_PRESENT; + + switch (axis) + { + case 0: + return joystick_state[0].axis[0]; + case 1: + return joystick_state[0].axis[1]; + case 2: + return joystick_state[0].axis[2]; + case 3: + return joystick_state[0].axis[3]; + default: + return 0; + } +} + static int joystick_standard_read_axis_6button(void *p, int axis) { if (!JOYSTICK_PRESENT(0)) @@ -227,6 +248,22 @@ const joystick_if_t joystick_standard_4button = {"X axis", "Y axis"}, {"Button 1", "Button 2", "Button 3", "Button 4"} }; +const joystick_if_t joystick_4axis_4button = +{ + "4-axis 4-button joystick", + joystick_standard_init, + joystick_standard_close, + joystick_standard_read_4button, + joystick_standard_write, + joystick_standard_read_axis_4axis, + joystick_standard_a0_over, + 4, + 4, + 0, + 1, + {"X axis", "Y axis", "Z axis", "zX axis"}, + {"Button 1", "Button 2", "Button 3", "Button 4"} +}; const joystick_if_t joystick_standard_6button = { "Standard 6-button joystick", diff --git a/src/game/joystick_standard.h b/src/game/joystick_standard.h index 26b16998e..4aa593f0d 100644 --- a/src/game/joystick_standard.h +++ b/src/game/joystick_standard.h @@ -37,5 +37,6 @@ extern const joystick_if_t joystick_standard; extern const joystick_if_t joystick_standard_4button; +extern const joystick_if_t joystick_4axis_4button; extern const joystick_if_t joystick_standard_6button; extern const joystick_if_t joystick_standard_8button; diff --git a/src/game/joystick_sw_pad.c b/src/game/joystick_sw_pad.c index 09030d8ad..5a8c0d284 100644 --- a/src/game/joystick_sw_pad.c +++ b/src/game/joystick_sw_pad.c @@ -60,9 +60,9 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "timer.h" #include "gameport.h" #include "joystick_sw_pad.h" diff --git a/src/game/joystick_tm_fcs.c b/src/game/joystick_tm_fcs.c index 69fa19d2b..afb4ac1b5 100644 --- a/src/game/joystick_tm_fcs.c +++ b/src/game/joystick_tm_fcs.c @@ -39,9 +39,9 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "timer.h" #include "gameport.h" #include "joystick_standard.h" diff --git a/src/hwm.c b/src/hwm.c new file mode 100644 index 000000000..b3142c7a4 --- /dev/null +++ b/src/hwm.c @@ -0,0 +1,36 @@ +/* + * 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. + * + * Common functions for hardware monitor chips. + * + * Version: @(#)hwm.c 1.0.0 2020/03/22 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ + +#include +#include "device.h" +#include "hwm.h" + + +hwm_values_t hwm_values; + + +void +hwm_set_values(hwm_values_t new_values) +{ + hwm_values = new_values; +} + + +hwm_values_t* +hwm_get_values() +{ + return &hwm_values; +} diff --git a/src/hwm.h b/src/hwm.h new file mode 100644 index 000000000..c5d482fb7 --- /dev/null +++ b/src/hwm.h @@ -0,0 +1,38 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for the hardware monitor chips. + * + * Version: @(#)hwm.h 1.0.0 2020/03/21 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#ifndef EMU_HWM_H +# define EMU_HWM_H + + +#define VDIV(v, r1, r2) (((v) * (r2)) / ((r1) + (r2))) + + +typedef struct _hwm_values_ { + uint16_t fans[4]; + uint8_t temperatures[4]; + uint8_t voltages[8]; +} hwm_values_t; + + +extern void hwm_set_values(hwm_values_t new_values); +extern hwm_values_t* hwm_get_values(); + + +extern const device_t w83781d_device; +extern const device_t as99127f_device; + + +#endif /*EMU_HWM_H*/ diff --git a/src/hwm_w83781d.c b/src/hwm_w83781d.c new file mode 100644 index 000000000..1f6b3ab26 --- /dev/null +++ b/src/hwm_w83781d.c @@ -0,0 +1,482 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Winbond W83781D hardware monitoring chip. + * + * Version: @(#)hwm_w83781d.c 1.0.0 2020/03/21 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "smbus.h" +#include "hwm.h" + + +#define W83781D_SMBUS 0x10000 +#define W83781D_AS99127F 0x20000 +#define W83781D_VENDOR_ID ((dev->local & W83781D_AS99127F) ? 0x12C3 : 0x5CA3) + +#define CLAMP(a, min, max) (((a) < (min)) ? (min) : (((a) > (max)) ? (max) : (a))) +#define W83781D_RPM_TO_REG(r, d) CLAMP(1350000 / (r * d), 1, 255) +#define W83781D_TEMP_TO_REG(t) ((t) * 8) << 5 + + +typedef struct { + uint32_t local; + hwm_values_t* values; + + uint8_t regs[64]; + uint8_t regs_bank1[6]; + uint8_t regs_bank2[6]; + uint8_t addr_register; + uint8_t data_register; + + uint8_t smbus_addr_main; + uint8_t smbus_addr_temp2; + uint8_t smbus_addr_temp3; + uint8_t hbacs; + uint8_t active_bank; +} w83781d_t; + + +static uint8_t w83781d_isa_read(uint16_t port, void *priv); +static uint8_t w83781d_smbus_read_byte(uint8_t addr, void *priv); +static uint8_t w83781d_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv); +static uint16_t w83781d_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv); +static uint8_t w83781d_read(w83781d_t *dev, uint8_t reg, uint8_t bank); +static void w83781d_isa_write(uint16_t port, uint8_t val, void *priv); +static void w83781d_smbus_write_byte(uint8_t addr, uint8_t val, void *priv); +static void w83781d_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv); +static void w83781d_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv); +static uint8_t w83781d_write(w83781d_t *dev, uint8_t reg, uint8_t val, uint8_t bank); +static void w83781d_reset(w83781d_t *dev, uint8_t initialization); + + +static void +w83781d_remap(w83781d_t *dev) +{ + if (!(dev->local & W83781D_SMBUS)) return; + + smbus_removehandler(0x00, 0x80, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_main) smbus_sethandler(dev->smbus_addr_main, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_temp2) smbus_sethandler(dev->smbus_addr_temp2, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); + + if (dev->smbus_addr_temp3) smbus_sethandler(dev->smbus_addr_temp3, 1, + w83781d_smbus_read_byte, w83781d_smbus_read_byte_cmd, w83781d_smbus_read_word_cmd, NULL, + w83781d_smbus_write_byte, w83781d_smbus_write_byte_cmd, w83781d_smbus_write_word_cmd, NULL, + dev); +} + + +static uint8_t +w83781d_isa_read(uint16_t port, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t ret = 0xFF; + + switch (port - (dev->local & 0xFFFF)) { + case 0x0: + ret = dev->addr_register & 0x7F; + break; + case 0x1: + ret = w83781d_read(dev, dev->addr_register, dev->active_bank); + + if (dev->active_bank == 0 && + (dev->addr_register == 0x41 || dev->addr_register == 0x43 || dev->addr_register == 0x45 || dev->addr_register == 0x56 || + (dev->addr_register >= 0x60 && dev->addr_register < 0x7F))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; + } + + return ret; +} + + +static uint8_t +w83781d_smbus_read_byte(uint8_t addr, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + return w83781d_read(dev, dev->addr_register, 0); +} + + +static uint8_t +w83781d_smbus_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + return w83781d_read(dev, cmd, 0); +} + + +static uint16_t +w83781d_smbus_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t rethi = 0; + uint8_t retlo = 0; + uint8_t bank = 0; + + if (addr == dev->smbus_addr_temp2 || addr == dev->smbus_addr_temp3) { + if (addr == dev->smbus_addr_temp2) + bank = 2; + else + bank = 3; + + switch (cmd & 0x3) { + case 0x0: + rethi = w83781d_read(dev, 0x50, bank); + retlo = w83781d_read(dev, 0x51, bank); + break; + case 0x1: + rethi = retlo = w83781d_read(dev, 0x52, bank); + break; + case 0x2: + rethi = w83781d_read(dev, 0x53, bank); + retlo = w83781d_read(dev, 0x54, bank); + break; + case 0x3: + rethi = w83781d_read(dev, 0x55, bank); + retlo = w83781d_read(dev, 0x56, bank); + break; + } + + return (retlo << 8) | rethi; /* byte-swapped for some reason */ + } + + return w83781d_read(dev, cmd, bank); +} + + +static uint8_t +w83781d_read(w83781d_t *dev, uint8_t reg, uint8_t bank) +{ + uint8_t ret = 0; + + if ((reg >> 4) == 0x5 && bank != 0) { + /* bank-switched temperature registers */ + if (bank == 1) + ret = dev->regs_bank1[reg - 0x50]; + else + ret = dev->regs_bank2[reg - 0x50]; + } else { + /* regular registers */ + if (reg == 0x4F) /* special case for two-byte vendor ID register */ + ret = dev->hbacs ? (W83781D_VENDOR_ID >> 8) : (W83781D_VENDOR_ID & 0xFF); + else if (reg >= 0x60) /* read auto-increment value RAM registers from their non-auto-increment locations */ + ret = dev->regs[reg - 0x40]; + else + ret = dev->regs[reg - 0x20]; + } + + return ret; +} + + +static void +w83781d_isa_write(uint16_t port, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + switch (port - (dev->local & 0xFFFF)) { + case 0x0: + dev->addr_register = val & 0x7F; + break; + case 0x1: + w83781d_write(dev, dev->addr_register, val, dev->active_bank); + + if (dev->active_bank == 0 && + (dev->addr_register == 0x41 || dev->addr_register == 0x43 || dev->addr_register == 0x45 || dev->addr_register == 0x56 || + (dev->addr_register >= 0x60 && dev->addr_register < 0x7F))) { + /* auto-increment registers */ + dev->addr_register++; + } + break; + } +} + + +static void +w83781d_smbus_write_byte(uint8_t addr, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + dev->addr_register = val; +} + + +static void +w83781d_smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + w83781d_write(dev, cmd, val, 0); +} + + +static void +w83781d_smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + uint8_t valhi = (val >> 8); + uint8_t vallo = (val & 0xFF); + uint8_t bank = 0; + + if (addr == dev->smbus_addr_temp2 || addr == dev->smbus_addr_temp3) { + if (addr == dev->smbus_addr_temp2) + bank = 2; + else + bank = 3; + + switch (cmd & 0x3) { + case 0x0: + w83781d_write(dev, 0x50, valhi, bank); + w83781d_write(dev, 0x51, vallo, bank); + break; + case 0x1: + w83781d_write(dev, 0x52, vallo, bank); + break; + case 0x2: + w83781d_write(dev, 0x53, valhi, bank); + w83781d_write(dev, 0x54, vallo, bank); + break; + case 0x3: + w83781d_write(dev, 0x55, valhi, bank); + w83781d_write(dev, 0x56, vallo, bank); + break; + break; + } + return; + } + + w83781d_write(dev, cmd, vallo, bank); +} + + +static uint8_t +w83781d_write(w83781d_t *dev, uint8_t reg, uint8_t val, uint8_t bank) +{ + uint8_t remap = 0; + + if ((reg >> 4) == 0x5 && bank != 0) { + /* bank-switched temperature registers */ + switch (reg) { + case 0x50: case 0x51: + /* read-only registers */ + return 0; + } + + if (bank == 1) + dev->regs_bank1[reg - 0x50] = val; + else + dev->regs_bank2[reg - 0x50] = val; + + return 1; + } + + /* regular registers */ + switch (reg) { + case 0x41: case 0x42: case 0x4F: case 0x58: + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2A: + case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6A: + /* read-only registers */ + return 0; + } + + if (reg >= 0x60) /* write auto-increment value RAM registers to their non-auto-increment locations */ + dev->regs[reg - 0x40] = val; + else + dev->regs[reg - 0x20] = val; + + switch (reg) { + case 0x40: + if (val >> 7) { + /* INITIALIZATION bit set: reset all registers except main SMBus address */ + w83781d_reset(dev, 1); + } + break; + case 0x47: + /* update FAN1/FAN2 values to match the new divisor */ + dev->regs[0x08] = W83781D_RPM_TO_REG(dev->values->fans[0], 1 << ((dev->regs[0x27] >> 4) & 0x3)); + dev->regs[0x09] = W83781D_RPM_TO_REG(dev->values->fans[1], 1 << ((dev->regs[0x27] >> 6) & 0x3)); + break; + case 0x48: + if (dev->local & W83781D_SMBUS) { + dev->smbus_addr_main = (dev->regs[0x28] & 0x7F); + remap = 1; + } + break; + case 0x4A: + if (dev->local & W83781D_SMBUS) { + /* DIS_T2 and DIS_T3 bits can disable those interfaces */ + if ((dev->regs[0x2A] >> 3) & 0x1) + dev->smbus_addr_temp2 = 0x00; + else + dev->smbus_addr_temp2 = 0x48 + (dev->regs[0x2A] & 0x7); + if (dev->regs[0x2A] >> 7) + dev->smbus_addr_temp3 = 0x00; + else + dev->smbus_addr_temp3 = 0x48 + ((dev->regs[0x2A] >> 4) & 0x7); + remap = 1; + } + break; + case 0x4B: + /* update FAN3 value to match the new divisor */ + dev->regs[0x0A] = W83781D_RPM_TO_REG(dev->values->fans[2], 1 << ((dev->regs[0x2B] >> 6) & 0x3)); + break; + case 0x4E: + dev->hbacs = (dev->regs[0x2E] & 0x80); + /* FIXME: Winbond's datasheet does not specify how BANKSEL[0:2] work */ + if (dev->regs[0x2E] & 0x1) + dev->active_bank = 0; + else if (dev->regs[0x2E] & 0x2) + dev->active_bank = 1; + else if (dev->regs[0x2E] & 0x4) + dev->active_bank = 2; + break; + } + + if (remap) + w83781d_remap(dev); + + return 1; +} + + +static void +w83781d_reset(w83781d_t *dev, uint8_t initialization) +{ + memset(dev->regs, 0, 64); + memset(dev->regs_bank1, 0, 6); + memset(dev->regs_bank2, 0, 6); + + /* WARNING: Array elements are register - 0x20. */ + uint8_t i; + for (i = 0; i <= 6; i++) + dev->regs[i] = dev->values->voltages[i]; + dev->regs[0x07] = dev->values->temperatures[0]; + for (i = 0; i <= 2; i++) + dev->regs[0x08 + i] = W83781D_RPM_TO_REG(dev->values->fans[i], 2); + dev->regs[0x20] = 0x01; + dev->regs[0x26] = 0x40; + dev->regs[0x27] = 0x50; + if (dev->local & W83781D_SMBUS) { + if (!initialization) /* don't reset main SMBus address if the reset was triggered by the INITIALIZATION bit */ + dev->smbus_addr_main = 0x2D; + dev->regs[0x28] = dev->smbus_addr_main; + dev->regs[0x2A] = 0x01; + dev->smbus_addr_temp2 = 0x48 + (dev->regs[0x2A] & 0x7); + dev->smbus_addr_temp3 = 0x48 + ((dev->regs[0x2A] >> 4) & 0x7); + } else { + dev->regs[0x28] = 0x00; + dev->regs[0x2A] = 0x88; + dev->smbus_addr_temp2 = dev->smbus_addr_temp3 = 0x00; + } + dev->regs[0x29] = 0x02; + dev->regs[0x2B] = 0x44; + dev->regs[0x2C] = 0x01; + dev->regs[0x2D] = 0x15; + dev->regs[0x2E] = 0x80; + dev->hbacs = (dev->regs[0x2E] & 0x80); + dev->regs[0x2F] = W83781D_VENDOR_ID >> 8; + dev->regs[0x37] = 0x80; + dev->regs[0x38] = (dev->local & W83781D_AS99127F) ? 0x31 : 0x10; + + /* WARNING: Array elements are register - 0x50. */ + uint16_t temp; + temp = W83781D_TEMP_TO_REG(dev->values->temperatures[1]); + dev->regs_bank1[0x0] = temp >> 8; + dev->regs_bank1[0x1] = temp & 0xFF; + dev->regs_bank1[0x3] = 0x4B; + dev->regs_bank1[0x5] = 0x50; + temp = W83781D_TEMP_TO_REG(dev->values->temperatures[2]); + dev->regs_bank2[0x0] = temp >> 8; + dev->regs_bank2[0x1] = temp & 0xFF; + dev->regs_bank2[0x3] = 0x4B; + dev->regs_bank2[0x5] = 0x50; + + w83781d_remap(dev); +} + + +static void +w83781d_close(void *priv) +{ + w83781d_t *dev = (w83781d_t *) priv; + + uint16_t isa_io = dev->local & 0xFFFF; + if (isa_io) + io_removehandler(isa_io, 2, w83781d_isa_read, NULL, NULL, w83781d_isa_write, NULL, NULL, dev); + + free(dev); +} + + +static void * +w83781d_init(const device_t *info) +{ + w83781d_t *dev = (w83781d_t *) malloc(sizeof(w83781d_t)); + memset(dev, 0, sizeof(w83781d_t)); + + dev->local = info->local; + dev->values = hwm_get_values(); + w83781d_reset(dev, 0); + + uint16_t isa_io = dev->local & 0xFFFF; + if (isa_io) + io_sethandler(isa_io, 2, w83781d_isa_read, NULL, NULL, w83781d_isa_write, NULL, NULL, dev); + + return dev; +} + + +const device_t w83781d_device = { + "Winbond W83781D Hardware Monitor", + DEVICE_ISA, + 0x295 | W83781D_SMBUS, + w83781d_init, w83781d_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +/* + * ASUS rebadged version of the W83781D. + * Some claim it's SMBus-only, yet the BIOS clearly reads most values over ISA, + * except TEMP3 (CPU Temperature) which is read over SMBus. + */ +const device_t as99127f_device = { + "ASUS AS99127F Hardware Monitor", + DEVICE_ISA, + 0x295 | W83781D_SMBUS | W83781D_AS99127F, + w83781d_init, w83781d_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/i82335.c b/src/i82335.c index 37cf60306..7be061601 100644 --- a/src/i82335.c +++ b/src/i82335.c @@ -4,7 +4,7 @@ #include #include #include -#include "io.h" +#include "86box_io.h" #include "mem.h" typedef struct diff --git a/src/ibm_5161.c b/src/ibm_5161.c index 7cf6fed64..2374bdec3 100644 --- a/src/ibm_5161.c +++ b/src/ibm_5161.c @@ -19,7 +19,7 @@ #include #include "86box.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "apm.h" #include "dma.h" #include "mem.h" @@ -27,7 +27,7 @@ #include "timer.h" #include "pit.h" #include "port_92.h" -#include "machine/machine.h" +#include "machine.h" #include "intel_sio.h" diff --git a/src/intel_flash.c b/src/intel_flash.c index 4dd041a48..396899621 100644 --- a/src/intel_flash.c +++ b/src/intel_flash.c @@ -25,7 +25,7 @@ #include "86box.h" #include "device.h" #include "mem.h" -#include "machine/machine.h" +#include "machine.h" #include "timer.h" #include "nvr.h" #include "plat.h" @@ -97,7 +97,7 @@ flash_read(uint32_t addr, void *p) case CMD_IID: if (addr & 1) - ret = dev->flash_id & 0xff; + ret = dev->flash_id & 0xff; else ret = 0x89; break; @@ -278,9 +278,12 @@ intel_flash_add_mappings(flash_t *dev) { int max = 2, i = 0; uint32_t base, fbase; + uint32_t sub = 0x20000; - if (biosmask == 0x3ffff) + if (biosmask == 0x3ffff) { + sub = 0x40000; max = 4; + } for (i = 0; i < max; i++) { if (biosmask == 0x3ffff) @@ -299,7 +302,7 @@ intel_flash_add_mappings(flash_t *dev) flash_write, flash_writew, flash_writel, dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); } - mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - 0x40000, 0x10000, + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000) - sub, 0x10000, flash_read, flash_readw, flash_readl, flash_write, flash_writew, flash_writel, dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); @@ -311,6 +314,16 @@ intel_flash_add_mappings(flash_t *dev) } +static void +intel_flash_reset(void *priv) +{ + flash_t *dev = (flash_t *) priv; + + dev->command = CMD_READ_ARRAY; + dev->status = 0; +} + + static void * intel_flash_init(const device_t *info) { @@ -330,7 +343,10 @@ intel_flash_init(const device_t *info) flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); swprintf(flash_name, l, L"%ls.bin", machine_name); - wcscpy(flash_path, flash_name); + if (wcslen(flash_name) <= 1024) + wcscpy(flash_path, flash_name); + else + wcsncpy(flash_path, flash_name, 1024); dev->flags = info->local & 0xff; @@ -455,11 +471,11 @@ intel_flash_close(void *p) const device_t intel_flash_bxt_ami_device = { "Intel 28F001BXT/28F002BXT Flash BIOS", - 0, + DEVICE_PCI, FLAG_INV_A16, intel_flash_init, intel_flash_close, - NULL, + intel_flash_reset, NULL, NULL, NULL, NULL }; @@ -468,11 +484,11 @@ const device_t intel_flash_bxt_ami_device = const device_t intel_flash_bxtw_ami_device = { "Intel 28F100BXT/28F200BXT Flash BIOS", - 0, + DEVICE_PCI, FLAG_INV_A16 | FLAG_WORD, intel_flash_init, intel_flash_close, - NULL, + intel_flash_reset, NULL, NULL, NULL, NULL }; #endif @@ -481,10 +497,10 @@ const device_t intel_flash_bxtw_ami_device = const device_t intel_flash_bxt_device = { "Intel 28F001BXT/28F002BXT Flash BIOS", - 0, 0, + DEVICE_PCI, 0, intel_flash_init, intel_flash_close, - NULL, + intel_flash_reset, NULL, NULL, NULL, NULL }; @@ -492,9 +508,9 @@ const device_t intel_flash_bxt_device = const device_t intel_flash_bxb_device = { "Intel 28F001BXB/28F002BXB Flash BIOS", - 0, FLAG_BXB, + DEVICE_PCI, FLAG_BXB, intel_flash_init, intel_flash_close, - NULL, + intel_flash_reset, NULL, NULL, NULL, NULL }; diff --git a/src/intel_piix.c b/src/intel_piix.c index d5fdfc36f..09c46f37c 100644 --- a/src/intel_piix.c +++ b/src/intel_piix.c @@ -10,13 +10,13 @@ * word 0 - base address * word 1 - bits 1-15 = byte count, bit 31 = end of transfer * - * Version: @(#)intel_piix.c 1.0.22 2018/10/31 + * Version: @(#)intel_piix.c 1.0.23 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -26,34 +26,92 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "cdrom/cdrom.h" -#include "cpu/cpu.h" -#include "scsi/scsi_device.h" -#include "scsi/scsi_cdrom.h" +#include "cdrom.h" +#include "cpu.h" +#include "scsi_device.h" +#include "scsi_cdrom.h" #include "dma.h" -#include "io.h" +#include "86box_io.h" #include "device.h" #include "apm.h" #include "keyboard.h" +#include "machine.h" #include "mem.h" +#include "timer.h" +#include "nvr.h" #include "pci.h" #include "pic.h" #include "port_92.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "disk/hdc_ide_sff8038i.h" -#include "disk/zip.h" -#include "machine/machine.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "hdc_ide_sff8038i.h" +#include "zip.h" +#include "machine.h" +#include "smbus.h" #include "piix.h" +#define ACPI_TIMER_FREQ 3579545 +#define PM_FREQ ACPI_TIMER_FREQ + +#define RSM_STS (1 << 15) +#define PWRBTN_STS (1 << 8) + +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) + +#define SCI_EN (1 << 0) +#define SUS_EN (1 << 13) + +#define ACPI_ENABLE 0xf1 +#define ACPI_DISABLE 0xf0 + + typedef struct { - int type; - uint8_t cur_readout_reg, - readout_regs[256], - regs[256], regs_ide[256]; + uint16_t io_base; + int base_channel; +} ddma_t; + + +typedef struct +{ + uint8_t gpireg[3], gporeg[4]; + uint16_t pmsts, pmen, + pmcntrl; + uint32_t glbctl; + uint64_t tmr_overflow_time; + int timer_index; +} power_t; + + +typedef struct +{ + uint8_t stat, next_stat, ctl, cmd, addr, + data0, data1, + index, + data[32]; + pc_timer_t command_timer; +} piix_smbus_t; + + +typedef struct +{ + uint8_t cur_readout_reg, rev, + type, func_shift, + max_func, pci_slot, + regs[4][256], + readout_regs[256], board_config[2]; + uint16_t func0_id, + usb_io_base, power_io_base, + smbus_io_base; sff8038i_t *bm[2]; + ddma_t ddma[2]; + power_t power; + piix_smbus_t smbus; + nvr_t * nvr; } piix_t; @@ -77,15 +135,489 @@ piix_log(const char *fmt, ...) #endif -static void -piix_bus_master_handlers(piix_t *dev, uint16_t old_base) +static +void do_irq(piix_t *dev, int func, int level) { - uint16_t base; + if ((dev == NULL) || (func > dev->max_func) /*|| + (dev->regs[func][0x3d] < PCI_INTA) || (dev->regs[func][0x3d] < PCI_INTD)*/) + return; - base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); + if (level) { +#ifdef WRONG_SPEC + pci_set_irq(dev->pci_slot, dev->regs[func][0x3d]); +#else + picintlevel(1 << 9); +#endif + piix_log("Raising IRQ...\n"); + } else { +#ifdef WRONG_SPEC + pci_clear_irq(dev->pci_slot, dev->regs[func][0x3d]); +#else + picintc(1 << 9); +#endif + piix_log("Lowering IRQ...\n"); + } +} - sff_bus_master_handlers(dev->bm[0], old_base, base, (dev->regs_ide[0x04] & 1)); - sff_bus_master_handlers(dev->bm[1], old_base + 8, base + 8, (dev->regs_ide[0x04] & 1)); + +static void +piix_ide_legacy_handlers(piix_t *dev, int bus) +{ + if (bus & 0x01) { + ide_pri_disable(); + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) + ide_pri_enable(); + } + + if (bus & 0x02) { + ide_sec_disable(); + if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) + ide_sec_enable(); + } +} + + +static void +piix_ide_bm_handlers(piix_t *dev) +{ + uint16_t base = (dev->regs[1][0x20] & 0xf0) | (dev->regs[1][0x21] << 8); + + sff_bus_master_handler(dev->bm[0], (dev->regs[1][0x04] & 1), base); + sff_bus_master_handler(dev->bm[1], (dev->regs[1][0x04] & 1), base + 8); +} + + +static uint8_t +kbc_alias_reg_read(uint16_t addr, void *p) +{ + uint8_t ret = inb(0x61); + + return ret; +} + + +static void +kbc_alias_reg_write(uint16_t addr, uint8_t val, void *p) +{ + outb(0x61, val); +} + + +static void +kbc_alias_update_io_mapping(piix_t *dev) +{ + io_removehandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_removehandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_removehandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + + if (dev->regs[0][0x4e] & 0x08) { + io_sethandler(0x0063, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_sethandler(0x0065, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + io_sethandler(0x0067, 1, kbc_alias_reg_read, NULL, NULL, kbc_alias_reg_write, NULL, NULL, dev); + } +} + + +static uint8_t +ddma_reg_read(uint16_t addr, void *p) +{ + ddma_t *dev = (ddma_t *) p; + uint8_t ret = 0xff; + int rel_ch = (addr & 0x30) >> 4; + int ch = dev->base_channel + rel_ch; + int dmab = (ch >= 4) ? 0xc0 : 0x00; + + switch (addr & 0x0f) { + case 0x00: + ret = dma[ch].ac & 0xff; + break; + case 0x01: + ret = (dma[ch].ac >> 8) & 0xff; + break; + case 0x02: + ret = dma[ch].page; + break; + case 0x04: + ret = dma[ch].cc & 0xff; + break; + case 0x05: + ret = (dma[ch].cc >> 8) & 0xff; + break; + case 0x09: + ret = inb(dmab + 0x08); + break; + } + + return ret; +} + + +static void +ddma_reg_write(uint16_t addr, uint8_t val, void *p) +{ + ddma_t *dev = (ddma_t *) p; + int rel_ch = (addr & 0x30) >> 4; + int ch = dev->base_channel + rel_ch; + int page_regs[4] = { 7, 3, 1, 2 }; + int i, dmab = (ch >= 4) ? 0xc0 : 0x00; + + switch (addr & 0x0f) { + case 0x00: + dma[ch].ab = (dma[ch].ab & 0xffff00) | val; + dma[ch].ac = dma[ch].ab; + break; + case 0x01: + dma[ch].ab = (dma[ch].ab & 0xff00ff) | (val << 8); + dma[ch].ac = dma[ch].ab; + break; + case 0x02: + if (ch >= 4) + outb(0x88 + page_regs[rel_ch], val); + else + outb(0x80 + page_regs[rel_ch], val); + break; + case 0x04: + dma[ch].cb = (dma[ch].cb & 0xffff00) | val; + dma[ch].cc = dma[ch].cb; + break; + case 0x05: + dma[ch].cb = (dma[ch].cb & 0xff00ff) | (val << 8); + dma[ch].cc = dma[ch].cb; + break; + case 0x08: + outb(dmab + 0x08, val); + break; + case 0x09: + outb(dmab + 0x09, val); + break; + case 0x0a: + outb(dmab + 0x0a, val); + break; + case 0x0b: + outb(dmab + 0x0b, val); + break; + case 0x0d: + outb(dmab + 0x0d, val); + break; + case 0x0e: + for (i = 0; i < 4; i++) + outb(dmab + 0x0a, i); + break; + case 0x0f: + outb(dmab + 0x0a, (val << 2) | rel_ch); + break; + } +} + + +static void +ddma_update_io_mapping(piix_t *dev, int n) +{ + int base_reg = 0x92 + (n << 1); + + if (dev->ddma[n].io_base != 0x0000) + io_removehandler(dev->usb_io_base, 0x40, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->ddma[n]); + + dev->ddma[n].io_base = (dev->regs[0][base_reg] & ~0x3f) | (dev->regs[0][base_reg + 1] << 8); + + if (dev->ddma[n].io_base != 0x0000) + io_sethandler(dev->ddma[n].io_base, 0x40, ddma_reg_read, NULL, NULL, ddma_reg_write, NULL, NULL, &dev->ddma[n]); +} + + +static uint8_t +usb_reg_read(uint16_t addr, void *p) +{ + uint8_t ret = 0xff; + + switch (addr & 0x1f) { + case 0x10: case 0x11: case 0x12: case 0x13: + /* Port status */ + ret = 0x00; + break; + } + + return ret; +} + + +static void +usb_reg_write(uint16_t addr, uint8_t val, void *p) +{ +} + + +static void +usb_update_io_mapping(piix_t *dev) +{ + if (dev->usb_io_base != 0x0000) + io_removehandler(dev->usb_io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); + + dev->usb_io_base = (dev->regs[2][0x20] & ~0x1f) | (dev->regs[2][0x21] << 8); + + if ((dev->regs[2][PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb_io_base != 0x0000)) + io_sethandler(dev->usb_io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); +} + + +static uint32_t +power_reg_readl(uint16_t addr, void *p) +{ + piix_t *dev = (piix_t *) p; + uint32_t timer; + uint32_t ret = 0xffffffff; + + switch (addr & 0x3c) { + case 0x08: + /* ACPI timer */ + timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + timer &= 0x00ffffff; + ret = timer; + break; + } + + piix_log("ACPI: Read L %08X from %04X\n", ret, addr); + + return ret; +} + + +static uint16_t +power_reg_readw(uint16_t addr, void *p) +{ + piix_t *dev = (piix_t *) p; + uint16_t ret = 0xffff; + uint32_t ret32; + + switch (addr & 0x3c) { + case 0x00: + break; + default: + ret32 = power_reg_readl(addr, p); + if (addr & 0x02) + ret = (ret32 >> 16) & 0xffff; + else + ret = ret32 & 0xffff; + break; + } + + piix_log("ACPI: Read W %08X from %04X\n", ret, addr); + + return ret; +} + + +static uint8_t +power_reg_read(uint16_t addr, void *p) +{ + piix_t *dev = (piix_t *) p; + uint32_t timer; + uint8_t ret = 0xff; + uint16_t ret16; + + switch (addr & 0x3f) { + case 0x30: case 0x31: case 0x32: + ret = dev->power.gporeg[addr & 0x03]; + piix_log("ACPI: Read B %02X from GPIREG %01X\n", ret, addr & 0x03); + break; + case 0x34: case 0x35: case 0x36: case 0x37: + ret = dev->power.gporeg[addr & 0x03]; + piix_log("ACPI: Read B %02X from GPOREG %01X\n", ret, addr & 0x03); + break; + default: + ret16 = power_reg_readw(addr, p); + if (addr & 0x01) + ret = (ret16 >> 8) & 0xff; + else + ret = ret16 & 0xff; + break; + } + + return ret; +} + + +static void +power_reg_write(uint16_t addr, uint8_t val, void *p) +{ + piix_t *dev = (piix_t *) p; + + piix_log("ACPI: Write %02X to %04X\n", val, addr); + + switch (addr & 0x3f) { + case 0x34: case 0x35: case 0x36: case 0x37: + dev->power.gporeg[addr & 0x03] = val; + break; + } +} + + +static void +power_update_io_mapping(piix_t *dev) +{ + if (dev->power_io_base != 0x0000) + io_removehandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); + + dev->power_io_base = (dev->regs[3][0x41] << 8) | (dev->regs[3][0x40] & 0xc0); + + if ((dev->regs[3][0x80] & 0x01) && (dev->power_io_base != 0x0000)) + io_sethandler(dev->power_io_base, 0x40, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); +} + + +static uint8_t +smbus_reg_read(uint16_t addr, void *priv) +{ + piix_t *dev = (piix_t *) priv; + uint8_t ret = 0x00; + + switch (addr - dev->smbus_io_base) { + case 0x00: + ret = dev->smbus.stat; + break; + case 0x02: + dev->smbus.index = 0; + ret = dev->smbus.ctl; + break; + case 0x03: + ret = dev->smbus.cmd; + break; + case 0x04: + ret = dev->smbus.addr; + break; + case 0x05: + ret = dev->smbus.data0; + break; + case 0x06: + ret = dev->smbus.data1; + break; + case 0x07: + ret = dev->smbus.data[dev->smbus.index++]; + if (dev->smbus.index > 31) + dev->smbus.index = 0; + break; + } + + piix_log("smbus_reg_read %02x %02x\n", addr - dev->smbus_io_base, ret); + + return ret; +} + + +static void +smbus_reg_write(uint16_t addr, uint8_t val, void *priv) +{ + piix_t *dev = (piix_t *) priv; + uint8_t smbus_addr; + uint8_t smbus_read; + uint16_t temp; + + piix_log("smbus_reg_write %02x %02x\n", addr - dev->smbus_io_base, val); + + dev->smbus.next_stat = 0; + switch (addr - dev->smbus_io_base) { + case 0x00: + /* some status bits are reset by writing 1 to them */ + for (smbus_addr = 0x02; smbus_addr <= 0x10; smbus_addr = smbus_addr << 1) { + if (val & smbus_addr) + dev->smbus.stat = dev->smbus.stat & ~smbus_addr; + } + break; + case 0x02: + dev->smbus.ctl = val & ~(0x40); /* START always reads 0 */ + if (val & 0x40) { /* dispatch command if START is set */ + smbus_addr = (dev->smbus.addr >> 1); + if (!smbus_has_device(smbus_addr)) { + /* raise DEV_ERR if no device is at this address */ + dev->smbus.next_stat = 0x4; + break; + } + smbus_read = (dev->smbus.addr & 0x01); + + switch ((val >> 2) & 0x7) { + case 0x0: /* quick R/W */ + dev->smbus.next_stat = 0x2; + break; + case 0x1: /* byte R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_byte(smbus_addr); + else + smbus_write_byte(smbus_addr, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + case 0x2: /* byte data R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_byte_cmd(smbus_addr, dev->smbus.cmd); + else + smbus_write_byte_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + case 0x3: /* word data R/W */ + if (smbus_read) { + temp = smbus_read_word_cmd(smbus_addr, dev->smbus.cmd); + dev->smbus.data0 = (temp & 0xFF); + dev->smbus.data1 = (temp >> 8); + } else { + temp = (dev->smbus.data1 << 8) | dev->smbus.data0; + smbus_write_word_cmd(smbus_addr, dev->smbus.cmd, temp); + } + dev->smbus.next_stat = 0x2; + break; + case 0x5: /* block R/W */ + if (smbus_read) + dev->smbus.data0 = smbus_read_block_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data); + else + smbus_write_block_cmd(smbus_addr, dev->smbus.cmd, dev->smbus.data, dev->smbus.data0); + dev->smbus.next_stat = 0x2; + break; + } + } + break; + case 0x03: + dev->smbus.cmd = val; + break; + case 0x04: + dev->smbus.addr = val; + break; + case 0x05: + dev->smbus.data0 = val; + break; + case 0x06: + dev->smbus.data1 = val; + break; + case 0x07: + dev->smbus.data[dev->smbus.index++] = val; + if (dev->smbus.index > 31) + dev->smbus.index = 0; + break; + } + + if (dev->smbus.next_stat) { + dev->smbus.stat = 0x1; + timer_disable(&dev->smbus.command_timer); + timer_set_delay_u64(&dev->smbus.command_timer, 10 * TIMER_USEC); + } +} + + +static void +smbus_inter(void *priv) +{ + piix_t *dev = (piix_t *) priv; + dev->smbus.stat = dev->smbus.next_stat; +} + + +static void +smbus_update_io_mapping(piix_t *dev) +{ + if (dev->smbus_io_base != 0x0000) + io_removehandler(dev->smbus_io_base, 0x10, smbus_reg_read, NULL, NULL, smbus_reg_write, NULL, NULL, dev); + + dev->smbus_io_base = (dev->regs[3][0x91] << 8) | (dev->regs[3][0x90] & 0xf0); + + if ((dev->regs[3][PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->regs[3][0xd2] & 0x01) && (dev->smbus_io_base != 0x0000)) + io_sethandler(dev->smbus_io_base, 0x10, smbus_reg_read, NULL, NULL, smbus_reg_write, NULL, NULL, dev); } @@ -93,161 +625,391 @@ static void piix_write(int func, int addr, uint8_t val, void *priv) { piix_t *dev = (piix_t *) priv; - uint8_t valxor; - uint16_t old_base; + uint8_t *fregs; - if ((func == 1) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ + /* Return on unsupported function. */ + if (func > dev->max_func) return; - if (func > 1) - return; + piix_log("PIIX function %i write: %02X to %02X\n", func, val, addr); + fregs = (uint8_t *) dev->regs[func]; - old_base = (dev->regs_ide[0x20] & 0xf0) | (dev->regs_ide[0x21] << 8); - - if (func == 1) { /*IDE*/ - piix_log("PIIX IDE write: %02X %02X\n", addr, val); - valxor = val ^ dev->regs_ide[addr]; - - switch (addr) { - case 0x04: - dev->regs_ide[0x04] = (val & 5) | 2; - if (valxor & 0x01) { - ide_pri_disable(); - ide_sec_disable(); - if (val & 0x01) { - if (dev->regs_ide[0x41] & 0x80) - ide_pri_enable(); - if (dev->regs_ide[0x43] & 0x80) - ide_sec_enable(); - } - - piix_bus_master_handlers(dev, old_base); - } - break; - case 0x07: - dev->regs_ide[0x07] = val & 0x3e; - break; - case 0x0d: - dev->regs_ide[0x0d] = val; - break; - - case 0x20: - dev->regs_ide[0x20] = (val & ~0x0f) | 1; - if (valxor) - piix_bus_master_handlers(dev, old_base); - break; - case 0x21: - dev->regs_ide[0x21] = val; - if (valxor) - piix_bus_master_handlers(dev, old_base); - break; - - case 0x40: - dev->regs_ide[0x40] = val; - break; - case 0x41: - dev->regs_ide[0x41] = val; - if (valxor & 0x80) { - ide_pri_disable(); - if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) - ide_pri_enable(); - } - break; - case 0x42: - dev->regs_ide[0x42] = val; - break; - case 0x43: - dev->regs_ide[0x43] = val; - if (valxor & 0x80) { - ide_sec_disable(); - if ((val & 0x80) && (dev->regs_ide[0x04] & 0x01)) - ide_sec_enable(); - } - break; - case 0x44: - if (dev->type >= 3) dev->regs_ide[0x44] = val; - break; - } - } else { - piix_log("PIIX writing value %02X to register %02X\n", val, addr); - valxor = val ^ dev->regs[addr]; - - if ((addr >= 0x0f) && (addr < 0x4c)) + if (func == 0) switch (addr) { + case 0x04: + fregs[0x04] = (val & 0x08) | 0x07; + break; + case 0x05: + if (dev->type > 1) + fregs[0x05] = (val & 0x01); + break; + case 0x07: + if ((val & 0x40) && (dev->type > 1)) + fregs[0x07] &= 0xbf; + if (val & 0x20) + fregs[0x07] &= 0xdf; + if (val & 0x10) + fregs[0x07] &= 0xef; + if (val & 0x08) + fregs[0x07] &= 0xf7; + if (val & 0x04) + fregs[0x07] &= 0xfb; + break; + case 0x4c: + fregs[0x4c] = val; + if (val & 0x80) { + if (dev->type > 1) + dma_alias_remove(); + else + dma_alias_remove_piix(); + } else { + if (dev->type > 1) + dma_alias_set(); + else + dma_alias_set_piix(); + } + break; + case 0x4e: + fregs[0x4e] = val; + keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); + if (dev->type >= 4) + kbc_alias_update_io_mapping(dev); + break; + case 0x4f: + if (dev->type > 3) + fregs[0x4f] = val & 0x07; + else if (dev->type == 3) + fregs[0x4f] = val & 0x01; + break; + case 0x60: case 0x61: case 0x62: case 0x63: + piix_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val); + fregs[addr] = val & 0x8f; + if (val & 0x80) + pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED); + else + pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf); + break; + case 0x64: + if (dev->type > 3) + fregs[0x64] = val; + break; + case 0x69: + if (dev->type > 1) + fregs[0x69] = val & 0xfe; + else + fregs[0x69] = val & 0xfa; + break; + case 0x6a: + switch (dev->type) { + case 1: + default: + fregs[0x6a] = (fregs[0x6a] & 0xfb) | (val & 0x04); + fregs[0x0e] = (val & 0x04) ? 0x80 : 0x00; + piix_log("PIIX: Write %02X\n", val); + dev->max_func = 0 + !!(val & 0x04); + break; + case 3: + fregs[0x6a] = val & 0xd1; + piix_log("PIIX3: Write %02X\n", val); + dev->max_func = 1 + !!(val & 0x10); + break; + case 4: + fregs[0x6a] = val & 0x80; + break; + } + break; + case 0x6b: + if ((dev->type > 1) && (val & 0x80)) + fregs[0x6b] &= 0x7f; return; - - switch (addr) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0e: - return; - - case 0x4c: - if (valxor) { - if (dev->type == 3) - dma_alias_remove(); - else - dma_alias_remove_piix(); - if (!(val & 0x80)) - dma_alias_set(); - } + case 0x70: case 0x71: + if ((dev->type > 1) && (addr == 0x71)) break; - case 0x4e: - keyboard_at_set_mouse_scan((val & 0x10) ? 1 : 0); - break; - case 0x60: - piix_log("Set IRQ routing: INT A -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + if (dev->type < 4) { + piix_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val); + if (dev->type > 1) + fregs[addr] = val & 0xef; else - pci_set_irq_routing(PCI_INTA, val & 0xf); - break; - case 0x61: - piix_log("Set IRQ routing: INT B -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTB, val & 0xf); - break; - case 0x62: - piix_log("Set IRQ routing: INT C -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTC, val & 0xf); - break; - case 0x63: - piix_log("Set IRQ routing: INT D -> %02X\n", val); - if (val & 0x80) - pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - else - pci_set_irq_routing(PCI_INTD, val & 0xf); - break; - case 0x6a: - if (dev->type == 3) - dev->regs[addr] = (val & 0xFD) | (dev->regs[addr] | 2); - else - dev->regs[addr] = (val & 0xFC) | (dev->regs[addr] | 3); - return; - case 0x70: - piix_log("Set MIRQ routing: MIRQ0 -> %02X\n", val); + fregs[addr] = val & 0xcf; if (val & 0x80) pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); else pci_set_mirq_routing(PCI_MIRQ0, val & 0xf); - break; - piix_log("MIRQ0 is %s\n", (val & 0x20) ? "disabled" : "enabled"); - case 0x71: - if (dev->type == 1) { - piix_log("Set MIRQ routing: MIRQ1 -> %02X\n", val); - if (val & 0x80) - pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); - else - pci_set_mirq_routing(PCI_MIRQ1, val & 0xf); - } - break; - } + piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled"); + } + break; + case 0x76: case 0x77: + if (dev->type > 1) + fregs[addr] = val & 0x87; + else + fregs[addr] = val & 0x8f; + break; + case 0x78: case 0x79: + if (dev->type < 4) + fregs[addr] = val; + break; + case 0x80: + if (dev->type > 1) + fregs[addr] = val & 0x7f; + break; + case 0x81: + if (dev->type > 1) + fregs[addr] = val & 0x0f; + break; + case 0x90: + if (dev->type > 3) + fregs[addr] = val; + break; + case 0x91: + if (dev->type > 3) + fregs[addr] = val & 0xfc; + break; + case 0x92: case 0x93: case 0x94: case 0x95: + if (dev->type == 4) { + if (addr & 0x01) + fregs[addr] = val & 0xc0; + else + fregs[addr] = val & 0xff; + ddma_update_io_mapping(dev, (addr >> 2) & 1); + } + break; + case 0xa0: + if (dev->type < 4) + fregs[addr] = val & 0x1f; + break; + case 0xa2: case 0xa5: case 0xa6: case 0xa8: + case 0xaa: case 0xac: case 0xae: + if (dev->type < 4) + fregs[addr] = val & 0xff; + break; + case 0xa3: case 0xab: + if (dev->type == 3) + fregs[addr] = val & 0x01; + break; + case 0xa4: + if (dev->type < 4) + fregs[addr] = val & 0xfb; + break; + case 0xa7: + if (dev->type == 3) + fregs[addr] = val & 0xef; + else if (dev->type < 3) + fregs[addr] = val; + break; + case 0xb0: + if (dev->type > 3) + fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73); + break; + case 0xb1: + if (dev->type > 3) + fregs[addr] = val & 0xdf; + break; + case 0xb2: + if (dev->type > 3) + fregs[addr] = val; + break; + case 0xb3: + if (dev->type > 3) + fregs[addr] = val & 0xfb; + break; + case 0xcb: + if (dev->type == 4) { + fregs[addr] = val & 0x3d; - dev->regs[addr] = val; + nvr_at_handler(0, 0x0070, dev->nvr); + nvr_at_handler(0, 0x0072, dev->nvr); + + if ((val & 0x01) && (dev->regs[2][0xff] & 0x10)) + nvr_at_handler(1, 0x0070, dev->nvr); + if (val & 0x04) + nvr_at_handler(1, 0x0072, dev->nvr); + + nvr_wp_set(!!(val & 0x08), 0, dev->nvr); + nvr_wp_set(!!(val & 0x10), 1, dev->nvr); + } + break; + } else if (func == 1) switch(addr) { /* IDE */ + case 0x04: + fregs[0x04] = (val & 5); + if (dev->type < 3) + fregs[0x04] |= 0x02; + piix_ide_legacy_handlers(dev, 0x03); + piix_ide_bm_handlers(dev); + break; + case 0x07: + if (val & 0x20) + fregs[0x07] &= 0xdf; + if (val & 0x10) + fregs[0x07] &= 0xef; + if (val & 0x08) + fregs[0x07] &= 0xf7; + break; + case 0x0d: + fregs[0x0d] = val & 0xf0; + break; + case 0x20: + fregs[0x20] = (val & 0xf0) | 1; + piix_ide_bm_handlers(dev); + break; + case 0x21: + fregs[0x21] = val; + piix_ide_bm_handlers(dev); + break; + case 0x3c: + piix_log("IDE IRQ write: %02X\n", val); + fregs[0x3c] = val; + break; + case 0x40: case 0x42: + fregs[addr] = val; + break; + case 0x41: case 0x43: + fregs[addr] = val & ((dev->type > 1) ? 0xf3 : 0xb3); + piix_ide_legacy_handlers(dev, 1 << !!(addr & 0x02)); + break; + case 0x44: + if (dev->type > 1) + fregs[0x44] = val; + break; + case 0x48: + if (dev->type > 3) + fregs[0x48] = val & 0x0f; + break; + case 0x4a: case 0x4b: + if (dev->type > 4) + fregs[addr] = val & 0x33; + break; + } else if (func == 2) switch(addr) { /* USB */ + case 0x04: + fregs[0x04] = (val & 5); + usb_update_io_mapping(dev); + break; + case 0x07: + if (val & 0x20) + fregs[0x07] &= 0xdf; + if (val & 0x10) + fregs[0x07] &= 0xef; + if (val & 0x08) + fregs[0x07] &= 0xf7; + break; + case 0x0d: + fregs[0x0d] = val & 0xf0; + break; + case 0x20: + fregs[0x20] = (val & 0xe0) | 1; + usb_update_io_mapping(dev); + break; + case 0x21: + fregs[0x21] = val; + usb_update_io_mapping(dev); + break; + case 0x3c: + fregs[0x3c] = val; + break; + case 0x6a: + if (dev->type < 4) + fregs[0x6a] = val & 0x01; + break; + case 0xc0: + fregs[0xc0] = val; + break; + case 0xc1: + fregs[0xc1] = val & 0xbf; + break; + case 0xff: + if (dev->type >= 4) { + fregs[addr] = val & 0x10; + nvr_at_handler(0, 0x0070, dev->nvr); + if ((dev->regs[0][0xcb] & 0x01) && (dev->regs[2][0xff] & 0x10)) + nvr_at_handler(1, 0x0070, dev->nvr); + } + break; + } else if (func == 3) switch(addr) { /* Power Management */ + case 0x04: + fregs[0x04] = (val & 1); + power_update_io_mapping(dev); + smbus_update_io_mapping(dev); + break; + case 0x07: + if (val & 0x08) + fregs[0x07] &= 0xf7; + break; +#if 0 + case 0x3c: + fregs[0x3c] = val; + break; +#endif + case 0x40: + fregs[0x40] = (val & 0xc0) | 1; + power_update_io_mapping(dev); + break; + case 0x41: + fregs[0x41] = val; + power_update_io_mapping(dev); + break; + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x48: case 0x49: + case 0x4c: case 0x4d: case 0x4e: + case 0x54: case 0x55: case 0x56: case 0x57: + case 0x59: case 0x5a: + case 0x5c: case 0x5d: case 0x5e: case 0x5f: + case 0x60: case 0x61: case 0x62: + case 0x64: case 0x65: + case 0x67: case 0x68: case 0x69: + case 0x6c: case 0x6e: case 0x6f: + case 0x70: case 0x71: + case 0x74: case 0x77: case 0x78: case 0x79: + case 0x7c: case 0x7d: + case 0xd3: case 0xd4: + case 0xd5: + fregs[addr] = val; + break; + case 0x4a: + fregs[addr] = val & 0x73; + break; + case 0x4b: + fregs[addr] = val & 0x01; + break; + case 0x4f: case 0x80: case 0xd2: + fregs[addr] = val & 0x0f; + if (addr == 0x80) + power_update_io_mapping(dev); + else if (addr == 0xd2) + smbus_update_io_mapping(dev); + break; + case 0x50: + fregs[addr] = val & 0x3f; + break; + case 0x51: + fregs[addr] = val & 0x58; + break; + case 0x52: + fregs[addr] = val & 0x7f; + break; + case 0x58: + fregs[addr] = val & 0x77; + break; + case 0x5b: + fregs[addr] = val & 0x03; + break; + case 0x63: + fregs[addr] = val & 0xf7; + break; + case 0x66: + fregs[addr] = val & 0xef; + break; + case 0x6a: case 0x72: case 0x7a: case 0x7e: + fregs[addr] = val & 0x1f; + break; + case 0x6d: case 0x75: + fregs[addr] = val & 0x80; + break; + case 0x90: + fregs[0x90] = (val & 0xf0) | 1; + smbus_update_io_mapping(dev); + break; + case 0x91: + fregs[0x91] = val; + smbus_update_io_mapping(dev); + break; } } @@ -256,133 +1018,17 @@ static uint8_t piix_read(int func, int addr, void *priv) { piix_t *dev = (piix_t *) priv; + uint8_t ret = 0xff, *fregs; - if ((func == 1) && (dev->type & 0x100)) /* PB640's PIIX has no IDE part. */ - return 0xff; - if (func > 1) - return 0xff; + /* Return on unsupported function. */ + if (func <= dev->max_func) { + fregs = (uint8_t *) dev->regs[func]; + ret = fregs[addr]; - if (func == 1) { /*IDE*/ - if (addr == 4) - return (dev->regs_ide[addr] & 5) | 2; - else if (addr == 5) - return 0; - else if (addr == 6) - return 0x80; - else if (addr == 7) - return dev->regs_ide[addr] & 0x3E; - else if (addr == 0xD) - return dev->regs_ide[addr] & 0xF0; - else if (addr == 0x20) - return (dev->regs_ide[addr] & 0xF0) | 1; - else if (addr == 0x22) - return 0; - else if (addr == 0x23) - return 0; - else if (addr == 0x41) { - if (dev->type == 3) - return dev->regs_ide[addr] & 0xF3; - else - return dev->regs_ide[addr] & 0xB3; - } else if (addr == 0x43) { - if (dev->type == 3) - return dev->regs_ide[addr] & 0xF3; - else - return dev->regs_ide[addr] & 0xB3; - } else - return dev->regs_ide[addr]; - } else { - if ((addr & 0xFC) == 0x60) - return dev->regs[addr] & 0x8F; - - if (addr == 4) { - if (dev->type & 0x100) - return (dev->regs[addr] & 0x80) | 0x0F; - else - return (dev->regs[addr] & 0x80) | 7; - } else if (addr == 5) { - if (dev->type == 3) - return dev->regs[addr] & 1; - else - return 0; - } else if (addr == 6) - return dev->regs[addr] & 0x80; - else if (addr == 7) { - if (dev->type == 3) - return dev->regs[addr]; - else { - if (dev->type & 0x100) - return dev->regs[addr] & 0x02; - else - return dev->regs[addr] & 0x3E; - } - } else if (addr == 0x4E) - return (dev->regs[addr] & 0xEF) | keyboard_at_get_mouse_scan(); - else if (addr == 0x69) - return dev->regs[addr] & 0xFE; - else if (addr == 0x6A) { - if (dev->type == 3) - return dev->regs[addr] & 0xD1; - else - return dev->regs[addr] & 0x07; - } else if (addr == 0x6B) { - if (dev->type == 3) - return dev->regs[addr] & 0x80; - else - return 0; - } - else if (addr == 0x70) { - if (dev->type == 3) - return dev->regs[addr] & 0xEF; - else - return dev->regs[addr] & 0xCF; - } else if (addr == 0x71) { - if (dev->type == 3) - return 0; - else - return dev->regs[addr] & 0xCF; - } else if (addr == 0x76) { - if (dev->type == 3) - return dev->regs[addr] & 0x87; - else - return dev->regs[addr] & 0x8F; - } else if (addr == 0x77) { - if (dev->type == 3) - return dev->regs[addr] & 0x87; - else - return dev->regs[addr] & 0x8F; - } else if (addr == 0x80) { - if (dev->type == 3) - return dev->regs[addr] & 0x7F; - else if (dev->type == 1) - return 0; - } else if (addr == 0x82) { - if (dev->type == 3) - return dev->regs[addr] & 0x0F; - else - return 0; - } else if (addr == 0xA0) - return dev->regs[addr] & 0x1F; - else if (addr == 0xA3) { - if (dev->type == 3) - return dev->regs[addr] & 1; - else - return 0; - } else if (addr == 0xA7) { - if (dev->type == 3) - return dev->regs[addr]; - else - return dev->regs[addr] & 0xEF; - } else if (addr == 0xAB) { - if (dev->type == 3) - return dev->regs[addr]; - else - return dev->regs[addr] & 0xFE; - } else - return dev->regs[addr]; + piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); } - return 0; + return ret; } @@ -391,7 +1037,11 @@ board_write(uint16_t port, uint8_t val, void *priv) { piix_t *dev = (piix_t *) priv; - if (port == 0x00e0) + if (port == 0x0078) + dev->board_config[0] = val; + else if (port == 0x0079) + dev->board_config[1] = val; + else if (port == 0x00e0) dev->cur_readout_reg = val; else if (port == 0x00e1) dev->readout_regs[dev->cur_readout_reg] = val; @@ -402,9 +1052,13 @@ static uint8_t board_read(uint16_t port, void *priv) { piix_t *dev = (piix_t *) priv; - uint8_t ret = 0xff; + uint8_t ret = 0x64; - if (port == 0x00e0) + if (port == 0x0078) + ret = dev->board_config[0]; + else if (port == 0x0079) + ret = dev->board_config[1]; + else if (port == 0x00e0) ret = dev->cur_readout_reg; else if (port == 0x00e1) ret = dev->readout_regs[dev->cur_readout_reg]; @@ -414,89 +1068,137 @@ board_read(uint16_t port, void *priv) static void -piix_reset_hard(void *priv) +piix_reset_hard(piix_t *dev) { - piix_t *piix = (piix_t *) priv; + int i; + uint8_t *fregs; - uint16_t old_base = (piix->regs_ide[0x20] & 0xf0) | (piix->regs_ide[0x21] << 8); + uint16_t old_base = (dev->regs[1][0x20] & 0xf0) | (dev->regs[1][0x21] << 8); - if (!(piix->type & 0x100)) { /* PB640's PIIX has no IDE part. */ - sff_bus_master_reset(piix->bm[0], old_base); - sff_bus_master_reset(piix->bm[1], old_base + 8); + sff_bus_master_reset(dev->bm[0], old_base); + sff_bus_master_reset(dev->bm[1], old_base + 8); + + if (dev->type == 4) { + sff_set_irq_mode(dev->bm[0], 0); + sff_set_irq_mode(dev->bm[1], 0); } - memset(piix->regs, 0, 256); - memset(piix->regs_ide, 0, 256); +#ifdef ENABLE_PIIX_LOG + piix_log("piix_reset_hard()\n"); +#endif + ide_pri_disable(); + ide_sec_disable(); - piix->regs[0x00] = 0x86; piix->regs[0x01] = 0x80; /*Intel*/ - if (piix->type == 3) { - piix->regs[0x02] = 0x00; piix->regs[0x03] = 0x70; /*82371SB (PIIX3)*/ - } else { - piix->regs[0x02] = 0x2e; piix->regs[0x03] = 0x12; /*82371FB (PIIX)*/ + if (dev->type > 3) { + nvr_at_handler(0, 0x0072, dev->nvr); + nvr_wp_set(0, 0, dev->nvr); + nvr_wp_set(0, 1, dev->nvr); + nvr_at_handler(1, 0x0074, dev->nvr); + nvr_at_handler(1, 0x0076, dev->nvr); } - if (piix->type & 0x100) - piix->regs[0x04] = 0x06; + + /* Clear all 4 functions' arrays and set their vendor and device ID's. */ + for (i = 0; i < 4; i++) { + memset(dev->regs[i], 0, 256); + dev->regs[i][0x00] = 0x86; dev->regs[i][0x01] = 0x80; /* Intel */ + dev->regs[i][0x02] = (dev->func0_id & 0xff) + (i << dev->func_shift); + dev->regs[i][0x03] = (dev->func0_id >> 8); + } + + /* Function 0: PCI to ISA Bridge */ + fregs = (uint8_t *) dev->regs[0]; + piix_log("PIIX Function 0: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + fregs[0x04] = 0x07; + fregs[0x06] = 0x80; fregs[0x07] = 0x02; + if (dev->type == 4) + fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); else - piix->regs[0x04] = 0x07; - piix->regs[0x05] = 0x00; - piix->regs[0x06] = 0x80; piix->regs[0x07] = 0x02; - if (piix->type & 0x100) - piix->regs[0x08] = 0x02; /*A0 stepping*/ - else - piix->regs[0x08] = 0x00; /*A0 stepping*/ - piix->regs[0x09] = 0x00; piix->regs[0x0a] = 0x01; piix->regs[0x0b] = 0x06; - if (piix->type & 0x100) - piix->regs[0x0e] = 0x00; /*Single-function device*/ - else - piix->regs[0x0e] = 0x80; /*Multi-function device*/ - piix->regs[0x4c] = 0x4d; - piix->regs[0x4e] = 0x03; - if (piix->type == 3) - piix->regs[0x4f] = 0x00; - piix->regs[0x60] = piix->regs[0x61] = piix->regs[0x62] = piix->regs[0x63] = 0x80; - piix->regs[0x69] = 0x02; - piix->regs[0x70] = 0xc0; - if (piix->type != 3) - piix->regs[0x71] = 0xc0; - piix->regs[0x76] = piix->regs[0x77] = 0x0c; - piix->regs[0x78] = 0x02; piix->regs[0x79] = 0x00; - if (piix->type == 3) { - piix->regs[0x80] = piix->regs[0x82] = 0x00; - } - piix->regs[0xa0] = 0x08; - piix->regs[0xa2] = piix->regs[0xa3] = 0x00; - piix->regs[0xa4] = piix->regs[0xa5] = piix->regs[0xa6] = piix->regs[0xa7] = 0x00; - piix->regs[0xa8] = 0x0f; - piix->regs[0xaa] = piix->regs[0xab] = 0x00; - piix->regs[0xac] = 0x00; - piix->regs[0xae] = 0x00; + fregs[0x08] = dev->rev; + fregs[0x09] = 0x00; + fregs[0x0a] = 0x01; fregs[0x0b] = 0x06; + fregs[0x0e] = (dev->type > 1) ? 0x80 : 0x00; + fregs[0x4c] = 0x4d; + fregs[0x4e] = 0x03; + fregs[0x60] = fregs[0x61] = fregs[0x62] = fregs[0x63] = 0x80; + fregs[0x64] = (dev->type > 3) ? 0x10 : 0x00; + fregs[0x69] = 0x02; + fregs[0x70] = (dev->type < 4) ? 0x80 : 0x00; + fregs[0x71] = (dev->type < 3) ? 0x80 : 0x00; + fregs[0x76] = fregs[0x77] = (dev->type > 1) ? 0x04 : 0x0c; + fregs[0x78] = (dev->type < 4) ? 0x02 : 0x00; + fregs[0xa0] = (dev->type < 4) ? 0x08 : 0x00; + fregs[0xa8] = (dev->type < 4) ? 0x0f : 0x00; + if (dev->type == 4) + fregs[0xb0] = (is_pentium) ? 0x00 : 0x04; + fregs[0xcb] = (dev->type > 3) ? 0x21 : 0x00; + dev->max_func = 0; - piix->regs_ide[0x00] = 0x86; piix->regs_ide[0x01] = 0x80; /*Intel*/ - if (piix->type == 3) { - piix->regs_ide[0x02] = 0x10; piix->regs_ide[0x03] = 0x70; /*82371SB (PIIX3)*/ - } else { - piix->regs_ide[0x02] = 0x30; piix->regs_ide[0x03] = 0x12; /*82371FB (PIIX)*/ + /* Function 1: IDE */ + fregs = (uint8_t *) dev->regs[1]; + piix_log("PIIX Function 1: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + fregs[0x04] = (dev->type > 3) ? 0x05 : 0x07; + fregs[0x06] = 0x80; fregs[0x07] = 0x02; + if (dev->type == 4) + fregs[0x08] = dev->rev & 0x07; + else + fregs[0x08] = dev->rev; + fregs[0x09] = 0x80; + fregs[0x0a] = 0x01; fregs[0x0b] = 0x01; + fregs[0x20] = 0x01; + dev->max_func = 0; /* It starts with IDE disabled, then enables it. */ + + /* Function 2: USB */ + if (dev->type > 1) { + fregs = (uint8_t *) dev->regs[2]; + piix_log("PIIX Function 2: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + fregs[0x04] = 0x05; + fregs[0x06] = 0x80; fregs[0x07] = 0x02; + if (dev->type == 4) + fregs[0x08] = dev->rev & 0x07; + else + fregs[0x08] = dev->rev; + fregs[0x0a] = 0x03; fregs[0x0b] = 0x0c; + fregs[0x20] = 0x01; + fregs[0x3d] = 0x04; + fregs[0x60] = (dev->type > 3) ? 0x10: 0x00; + fregs[0x6a] = (dev->type == 3) ? 0x01 : 0x00; + fregs[0xc1] = 0x20; + fregs[0xff] = (dev->type > 3) ? 0x10 : 0x00; + dev->max_func = 1; /* It starts with USB disabled, then enables it. */ + } + + /* Function 3: Power Management */ + if (dev->type > 3) { + fregs = (uint8_t *) dev->regs[3]; + piix_log("PIIX Function 3: 8086:%02X%02X\n", fregs[0x03], fregs[0x02]); + fregs[0x06] = 0x80; fregs[0x07] = 0x02; + fregs[0x08] = (dev->rev & 0x08) ? 0x02 : (dev->rev & 0x07); + fregs[0x0a] = 0x80; fregs[0x0b] = 0x06; + /* NOTE: The Specification Update says this should default to 0x00 and be read-only. */ +#ifdef WRONG_SPEC + fregs[0x3d] = 0x01; +#endif + fregs[0x40] = 0x01; + fregs[0x90] = 0x01; + dev->max_func = 3; } - piix->regs_ide[0x04] = 0x03; piix->regs_ide[0x05] = 0x00; - piix->regs_ide[0x06] = 0x80; piix->regs_ide[0x07] = 0x02; - piix->regs_ide[0x08] = 0x00; - piix->regs_ide[0x09] = 0x80; piix->regs_ide[0x0a] = 0x01; piix->regs_ide[0x0b] = 0x01; - piix->regs_ide[0x0d] = 0x00; - piix->regs_ide[0x0e] = 0x00; - piix->regs_ide[0x20] = 0x01; piix->regs_ide[0x21] = piix->regs_ide[0x22] = piix->regs_ide[0x23] = 0x00; /*Bus master interface base address*/ - piix->regs_ide[0x40] = piix->regs_ide[0x42] = 0x00; - piix->regs_ide[0x41] = piix->regs_ide[0x43] = 0x00; - if (piix->type == 3) - piix->regs_ide[0x44] = 0x00; pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); - pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); - if (piix->type != 3) + if (dev->type < 4) + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + if (dev->type < 3) pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + + if (dev->type == 4) { + dev->power.gporeg[0] = 0xff; + dev->power.gporeg[1] = 0xbf; + dev->power.gporeg[2] = 0xff; + dev->power.gporeg[3] = 0x7f; + } } @@ -512,30 +1214,40 @@ piix_close(void *p) static void *piix_init(const device_t *info) { - piix_t *piix = (piix_t *) malloc(sizeof(piix_t)); - memset(piix, 0, sizeof(piix_t)); + int i; + CPU *cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu]; - pci_add_card(7, piix_read, piix_write, piix); + piix_t *dev = (piix_t *) malloc(sizeof(piix_t)); + memset(dev, 0, sizeof(piix_t)); - piix->type = info->local; + dev->type = info->local & 0x0f; + /* If (dev->type == 4) and (dev->rev & 0x08), then this is PIIX4E. */ + dev->rev = (info->local >> 4) & 0x0f; + dev->func_shift = info->local >> 8; + dev->func0_id = info->local >> 16; + + dev->pci_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, piix_read, piix_write, dev); + piix_log("PIIX%i: Added to slot: %02X\n", dev->type, dev->pci_slot); + + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + + if (dev->type > 3) + dev->nvr = device_add(&piix4_nvr_device); + + piix_reset_hard(dev); device_add(&apm_device); - - if (!(piix->type & 0x100)) { /* PB640's PIIX has no IDE part. */ - piix->bm[0] = device_add_inst(&sff8038i_device, 1); - piix->bm[1] = device_add_inst(&sff8038i_device, 2); - } - - piix_reset_hard(piix); - device_add(&port_92_pci_device); dma_alias_set(); - pci_enable_mirq(0); - pci_enable_mirq(1); + if (dev->type < 4) + pci_enable_mirq(0); + if (dev->type < 3) + pci_enable_mirq(1); - piix->readout_regs[1] = 0x40; + dev->readout_regs[1] = 0x40; /* Port E1 register 01 (TODO: Find how multipliers > 3.0 are defined): @@ -547,65 +1259,68 @@ static void 1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz; 1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */ - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].pci_speed) { - case 20000000: - piix->readout_regs[1] |= 0x30; - break; - case 25000000: - default: - piix->readout_regs[1] |= 0x00; - break; - case 30000000: - piix->readout_regs[1] |= 0x20; - break; - case 33333333: - piix->readout_regs[1] |= 0x10; - break; - } + if (cpu_busspeed <= 0x40000000) + dev->readout_regs[1] |= 0x30; + else if ((cpu_busspeed > 0x40000000) && (cpu_busspeed <= 0x50000000)) + dev->readout_regs[1] |= 0x00; + else if ((cpu_busspeed > 0x50000000) && (cpu_busspeed <= 0x60000000)) + dev->readout_regs[1] |= 0x20; + else if (cpu_busspeed > 0x60000000) + dev->readout_regs[1] |= 0x10; - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed) { - case 75000000: - piix->readout_regs[1] |= 0x82; /* 50 MHz * 1.5 multiplier */ - break; - case 90000000: - piix->readout_regs[1] |= 0x82; /* 60 MHz * 1.5 multiplier */ - break; - case 100000000: - if ((piix->readout_regs[1] & 0x30) == 0x10) - piix->readout_regs[1] |= 0x82; /* 66 MHz * 1.5 multiplier */ - else - piix->readout_regs[1] |= 0x02; /* 50 MHz * 2.0 multiplier */ - break; - case 12000000: - piix->readout_regs[1] |= 0x02; /* 60 MHz * 2.0 multiplier */ - break; - case 125000000: - piix->readout_regs[1] |= 0x00; /* 50 MHz * 2.5 multiplier */ - break; - case 133333333: - piix->readout_regs[1] |= 0x02; /* 66 MHz * 2.0 multiplier */ - break; - case 150000000: - if ((piix->readout_regs[1] & 0x30) == 0x20) - piix->readout_regs[1] |= 0x00; /* 60 MHz * 2.5 multiplier */ - else - piix->readout_regs[1] |= 0x80; /* 50 MHz * 3.0 multiplier */ - break; - case 166666666: - piix->readout_regs[1] |= 0x00; /* 66 MHz * 2.5 multiplier */ - break; - case 180000000: - piix->readout_regs[1] |= 0x80; /* 60 MHz * 3.0 multiplier */ - break; - case 200000000: - piix->readout_regs[1] |= 0x80; /* 66 MHz * 3.0 multiplier */ - break; - } + if (cpu_dmulti <= 1.5) + dev->readout_regs[1] |= 0x82; + else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0)) + dev->readout_regs[1] |= 0x02; + else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5)) + dev->readout_regs[1] |= 0x00; + else if (cpu_dmulti > 2.5) + dev->readout_regs[1] |= 0x80; - io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, piix); - io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, piix); + io_sethandler(0x0078, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); + io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev); - return piix; + dev->board_config[0] = 0xff; + /* Register 0x0079: */ + /* Bit 7: 0 = Keep password, 0 = Clear password. */ + /* Bit 6: 0 = NVRAM cleared by jumper, 1 = NVRAM normal. */ + /* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */ + /* Bit 4: External CPU clock (Switch 8). */ + /* Bit 3: External CPU clock (Switch 7). */ + /* 50 MHz: Switch 7 = Off, Switch 8 = Off. */ + /* 60 MHz: Switch 7 = On, Switch 8 = Off. */ + /* 66 MHz: Switch 7 = Off, Switch 8 = On. */ + /* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */ + /* Bit 0: 0 = 1.5x multiplier, 0 = 2x multiplier. */ + dev->board_config[1] = 0xe0; + if ((cpu_s->rspeed == 75000000) && (cpu_busspeed == 50000000)) + dev->board_config[1] |= 0x01; + else if ((cpu_s->rspeed == 90000000) && (cpu_busspeed == 60000000)) + dev->board_config[1] |= (0x01 | 0x08); + else if ((cpu_s->rspeed == 100000000) && (cpu_busspeed == 50000000)) + dev->board_config[1] |= 0x00; + else if ((cpu_s->rspeed == 100000000) && (cpu_busspeed == 66666666)) + dev->board_config[1] |= (0x01 | 0x10); + else if ((cpu_s->rspeed == 120000000) && (cpu_busspeed == 60000000)) + dev->board_config[1] |= 0x08; + else if ((cpu_s->rspeed == 133333333) && (cpu_busspeed == 66666666)) + dev->board_config[1] |= 0x10; + else + dev->board_config[1] |= 0x10; /* TODO: how are the overdrive processors configured? */ + + smbus_init(); + dev->smbus.stat = 0; + dev->smbus.ctl = 0; + dev->smbus.cmd = 0; + dev->smbus.addr = 0; + dev->smbus.data0 = 0; + dev->smbus.data1 = 0; + dev->smbus.index = 0; + for (i = 0; i < 32; i++) + dev->smbus.data[i] = 0; + timer_add(&dev->smbus.command_timer, smbus_inter, dev, 0); + + return dev; } @@ -613,21 +1328,7 @@ const device_t piix_device = { "Intel 82371FB (PIIX)", DEVICE_PCI, - 1, - piix_init, - piix_close, - NULL, - NULL, - NULL, - NULL, - NULL -}; - -const device_t piix_pb640_device = -{ - "Intel 82371FB (PIIX) (PB640)", - DEVICE_PCI, - 0x101, + 0x122e0101, piix_init, piix_close, NULL, @@ -641,7 +1342,35 @@ const device_t piix3_device = { "Intel 82371SB (PIIX3)", DEVICE_PCI, - 3, + 0x70000403, + piix_init, + piix_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const device_t piix4_device = +{ + "Intel 82371AB/EB (PIIX4/PIIX4E)", + DEVICE_PCI, + 0x71100004, + piix_init, + piix_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +const device_t piix4e_device = +{ + "Intel 82371EB (PIIX4E)", + DEVICE_PCI, + 0x71100094, piix_init, piix_close, NULL, diff --git a/src/intel_sio.c b/src/intel_sio.c index b9e3a07d3..d0a5da9f4 100644 --- a/src/intel_sio.c +++ b/src/intel_sio.c @@ -21,7 +21,7 @@ #include #include "86box.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "apm.h" #include "dma.h" #include "mem.h" @@ -29,7 +29,7 @@ #include "timer.h" #include "pit.h" #include "port_92.h" -#include "machine/machine.h" +#include "machine.h" #include "intel_sio.h" @@ -123,7 +123,7 @@ sio_write(int func, int addr, uint8_t val, void *priv) if (func > 0) return; - if (addr >= 0x0f && addr < 0x4c) + if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40)) return; /* The IB (original) variant of the SIO has no PCI IRQ steering. */ @@ -248,7 +248,7 @@ sio_config_read(uint16_t port, void *priv) case 5: ret = 0xd3; - switch (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].pci_speed) { + switch (cpu_pci_speed) { case 20000000: ret |= 0x0c; break; @@ -341,7 +341,7 @@ sio_init(const device_t *info) sio_t *sio = (sio_t *) malloc(sizeof(sio_t)); memset(sio, 0, sizeof(sio_t)); - pci_add_card(2, sio_read, sio_write, sio); + pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, sio); device_add(&apm_device); diff --git a/src/io.c b/src/io.c index 8e1ed59f8..6e53aafe2 100644 --- a/src/io.c +++ b/src/io.c @@ -25,9 +25,9 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "io.h" -#include "cpu/cpu.h" -#include "machine/m_amstrad.h" +#include "86box_io.h" +#include "cpu.h" +#include "m_amstrad.h" #define NPORTS 65536 /* PC/AT supports 64K ports */ @@ -333,9 +333,27 @@ inb(uint16_t port) io_log("IOTRACE(%04X): inb(%04x)=%02x\n", IO_TRACE, port, ret); #endif + /* if (port == 0x386) { + ret = 0x00; + found = 1; + } + + if (port == 0x406) { + ret = 0x00; + found = 1; + } + + if (port == 0xf87) { + ret = 0x00; + found = 1; + } */ + if (!found) sub_cycles(io_delay); + // if (!found) + // pclog("inb(%04X) = %02X\n", port, ret); + return(ret); } @@ -365,6 +383,9 @@ outb(uint16_t port, uint8_t val) if (!found) sub_cycles(io_delay); + // if (!found) + // pclog("outb(%04X, %02X)\n", port, val); + return; } diff --git a/src/isamem.c b/src/isamem.c index a6f29deb5..9a37909c2 100644 --- a/src/isamem.c +++ b/src/isamem.c @@ -74,8 +74,8 @@ #include #include #include "86box.h" -#include "machine/machine.h" -#include "io.h" +#include "machine.h" +#include "86box_io.h" #include "mem.h" #include "device.h" #include "ui.h" diff --git a/src/isartc.c b/src/isartc.c index 22da01027..c83460aaa 100644 --- a/src/isartc.c +++ b/src/isartc.c @@ -71,10 +71,10 @@ #include #include #include "86box.h" -#include "cpu/cpu.h" +#include "cpu.h" #include "timer.h" -#include "machine/machine.h" -#include "io.h" +#include "machine.h" +#include "86box_io.h" #include "device.h" #include "nvr.h" #include "ui.h" diff --git a/src/keyboard.c b/src/keyboard.c index 68f5017df..1c770f69d 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -23,7 +23,7 @@ #include #include #include "86box.h" -#include "machine/machine.h" +#include "machine.h" #include "keyboard.h" diff --git a/src/keyboard_at.c b/src/keyboard_at.c index 7da1c4380..c81f07bfa 100644 --- a/src/keyboard_at.c +++ b/src/keyboard_at.c @@ -26,22 +26,22 @@ #define HAVE_STDARG_H #include #include "86box.h" -#include "cpu/cpu.h" +#include "cpu.h" #include "timer.h" -#include "io.h" +#include "86box_io.h" #include "pic.h" #include "pit.h" #include "ppi.h" #include "mem.h" #include "device.h" -#include "machine/machine.h" -#include "machine/m_xt_xi8088.h" -#include "machine/m_at_t3100e.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "sound/sound.h" -#include "sound/snd_speaker.h" -#include "video/video.h" +#include "machine.h" +#include "m_xt_xi8088.h" +#include "m_at_t3100e.h" +#include "fdd.h" +#include "fdc.h" +#include "sound.h" +#include "snd_speaker.h" +#include "video.h" #include "keyboard.h" @@ -57,6 +57,8 @@ #define PS2_REFRESH_TIME (16 * TIMER_USEC) +#define RESET_DELAY_TIME (100 * 10) /* 600ms */ + #define CCB_UNUSED 0x80 #define CCB_TRANSLATE 0x40 #define CCB_PCMODE 0x20 @@ -95,7 +97,7 @@ typedef struct { uint8_t mem[0x100]; int out_new, out_delayed; - int last_irq; + int last_irq, reset_delay; uint32_t flags; @@ -568,6 +570,9 @@ static const scancode scancode_set3[512] = { }; +static void add_data_kbd(uint16_t val); + + #ifdef ENABLE_KEYBOARD_AT_LOG int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; @@ -667,11 +672,17 @@ kbd_poll(void *priv) (mouse_queue_start != mouse_queue_end)) { dev->out_new = mouse_queue[mouse_queue_start] | 0x100; mouse_queue_start = (mouse_queue_start + 1) & 0xf; - } else if (!(dev->status&STAT_OFULL) && dev->out_new == -1 && + } else if (!(dev->status & STAT_OFULL) && dev->out_new == -1 && !(dev->mem[0]&0x10) && (key_queue_start != key_queue_end)) { dev->out_new = key_queue[key_queue_start]; key_queue_start = (key_queue_start + 1) & 0xf; } + + if (dev->reset_delay) { + dev->reset_delay--; + if (!dev->reset_delay) + add_data_kbd(0xaa); + } } @@ -697,6 +708,9 @@ add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) uint8_t or = 0; uint8_t send; + if (dev->reset_delay) + return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); @@ -744,6 +758,9 @@ add_data_kbd(uint16_t val) uint8_t fake_shift[4]; uint8_t num_lock = 0, shift_states = 0; + if (dev->reset_delay) + return; + translate = translate || (keyboard_mode & 0x40) || xt_mode; translate = translate || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); @@ -1002,6 +1019,7 @@ write_output(atkbd_t *dev, uint8_t val) cpu_set_edx(); } } + /* Mask off the A20 stuff because we use mem_a20_key directly for that. */ dev->output_port = val; } @@ -1481,20 +1499,6 @@ write64_ami(void *priv, uint8_t val) dev->output_locked = 1; return 0; - case 0xca: /* read keyboard mode */ -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("ATkbd: AMI - read keyboard mode\n"); -#endif - add_data(dev, 0x00); /*ISA mode*/ - return 0; - - case 0xcb: /* set keyboard mode */ -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("ATkbd: AMI - set keyboard mode\n"); -#endif - dev->want60 = 1; - return 0; - case 0xef: /* ??? - sent by AMI486 */ #ifdef ENABLE_KEYBOARD_AT_LOG kbd_log("ATkbd: ??? - sent by AMI486\n"); @@ -1988,11 +1992,12 @@ do_command: #endif key_queue_start = key_queue_end = 0; /*Clear key queue*/ add_data_kbd(0xfa); - add_data_kbd(0xaa); /* Set scan code set to 2. */ keyboard_mode = (keyboard_mode & 0xfc) | 0x02; set_scancode_map(dev); + + dev->reset_delay = RESET_DELAY_TIME; break; default: @@ -2107,6 +2112,20 @@ do_command: set_enable_kbd(dev, 1); break; + case 0xca: /* read keyboard mode */ +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("ATkbd: AMI - read keyboard mode\n"); +#endif + add_data(dev, ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00); /*ISA mode*/ + break; + + case 0xcb: /* set keyboard mode */ +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("ATkbd: AMI - set keyboard mode\n"); +#endif + dev->want60 = 1; + break; + case 0xd0: /* read output port */ #ifdef ENABLE_KEYBOARD_AT_LOG kbd_log("ATkbd: read output port\n"); @@ -2191,6 +2210,9 @@ kbd_read(uint16_t port, void *priv) atkbd_t *dev = (atkbd_t *)priv; uint8_t ret = 0xff; + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + sub_cycles(ISA_CYCLES(8)); + if (((dev->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) && (port == 0x63)) port = 0x61; @@ -2270,7 +2292,7 @@ kbd_reset(void *priv) dev->first_write = 1; dev->status = STAT_UNLOCKED | STAT_CD; dev->mem[0] = 0x01; - if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) + // if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_XI8088) dev->mem[0] |= CCB_TRANSLATE; dev->wantirq = 0; write_output(dev, 0xcf); diff --git a/src/keyboard_xt.c b/src/keyboard_xt.c index 7f8be716c..e74e926fb 100644 --- a/src/keyboard_xt.c +++ b/src/keyboard_xt.c @@ -26,18 +26,18 @@ #include "86box.h" #include "device.h" #include "timer.h" -#include "floppy/fdd.h" -#include "machine/machine.h" -#include "machine/m_xt_t1000.h" -#include "io.h" +#include "fdd.h" +#include "machine.h" +#include "m_xt_t1000.h" +#include "86box_io.h" #include "pic.h" #include "pit.h" #include "ppi.h" #include "mem.h" #include "rom.h" -#include "sound/sound.h" -#include "sound/snd_speaker.h" -#include "video/video.h" +#include "sound.h" +#include "snd_speaker.h" +#include "video.h" #include "keyboard.h" diff --git a/src/lpt.c b/src/lpt.c index f67eba3cc..646cc2cd1 100644 --- a/src/lpt.c +++ b/src/lpt.c @@ -6,12 +6,11 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "lpt.h" #include "pic.h" -#include "sound/snd_lpt_dac.h" -#include "sound/snd_lpt_dss.h" -#include "printer/prt_devs.h" +#include "sound.h" +#include "prt_devs.h" lpt_port_t lpt_ports[3]; diff --git a/src/lpt.h b/src/lpt.h index c6a95fc4e..43a91a09a 100644 --- a/src/lpt.h +++ b/src/lpt.h @@ -53,3 +53,8 @@ extern char * lpt_device_get_name(int id); extern char * lpt_device_get_internal_name(int id); extern int lpt_device_get_from_internal_name(char *s); + +extern const lpt_device_t lpt_dac_device; +extern const lpt_device_t lpt_dac_stereo_device; + +extern const lpt_device_t dss_device; diff --git a/src/machine/m_amstrad.c b/src/machine/m_amstrad.c index 6a9b56b1c..d2c4325e3 100644 --- a/src/machine/m_amstrad.c +++ b/src/machine/m_amstrad.c @@ -48,31 +48,30 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pit.h" -#include "../ppi.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../game/gameport.h" -#include "../lpt.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../sound/sound.h" -#include "../sound/snd_speaker.h" -#include "../video/video.h" -#include "../video/vid_cga.h" -#include "../video/vid_ega.h" -#include "../video/vid_mda.h" -#include "../video/vid_paradise.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "nmi.h" +#include "pic.h" +#include "pit.h" +#include "ppi.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "keyboard.h" +#include "mouse.h" +#include "gameport.h" +#include "lpt.h" +#include "fdd.h" +#include "fdc.h" +#include "sound.h" +#include "snd_speaker.h" +#include "video.h" +#include "vid_cga.h" +#include "vid_ega.h" +#include "vid_mda.h" #include "machine.h" #include "m_amstrad.h" @@ -2508,7 +2507,7 @@ machine_amstrad_init(const machine_t *model, int type) mouse_set_poll(ms_poll, ams); } - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); } diff --git a/src/machine/m_at.c b/src/machine/m_at.c index 773ac6126..25666f7bc 100644 --- a/src/machine/m_at.c +++ b/src/machine/m_at.c @@ -8,15 +8,15 @@ * * Standard PC/AT implementation. * - * Version: @(#)m_at.c 1.0.11 2019/11/15 + * Version: @(#)m_at.c 1.0.12 2020/01/13 * * Authors: Fred N. van Kempen, * Miran Grca, * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * 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 @@ -40,26 +40,26 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" -#include "../pic.h" -#include "../pit.h" -#include "../dma.h" -#include "../mem.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../nvr.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../rom.h" -#include "../disk/hdc.h" +#include "86box.h" +#include "timer.h" +#include "pic.h" +#include "pit.h" +#include "dma.h" +#include "mem.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "nvr.h" +#include "gameport.h" +#include "keyboard.h" +#include "lpt.h" +#include "rom.h" +#include "hdc.h" #include "machine.h" void -machine_at_common_init_ex(const machine_t *model, int is_ibm) +machine_at_common_init_ex(const machine_t *model, int type) { machine_common_init(model); @@ -67,12 +67,12 @@ machine_at_common_init_ex(const machine_t *model, int is_ibm) pic2_init(); dma16_init(); - if (is_ibm) + if (type == 1) device_add(&ibmat_nvr_device); - else + else if (type == 0) device_add(&at_nvr_device); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); } @@ -237,6 +237,23 @@ machine_at_ibmxt286_init(const machine_t *model) return ret; } +#if defined(DEV_BRANCH) && defined(USE_SIEMENS) +int +machine_at_siemens_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/siemens/286BIOS.BIN", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ibm_common_init(model); + + return ret; +} +#endif #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) int diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index 35a969cc6..70c78226b 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -8,7 +8,7 @@ * * Implementation of 286 and 386SX machines. * - * Version: @(#)m_at_286_386sx.c 1.0.2 2019/11/19 + * Version: @(#)m_at_286_386sx.c 1.0.3 2020/01/22 * * Authors: Sarah Walker, * Miran Grca, @@ -22,22 +22,19 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../device.h" -#include "../chipset/chipset.h" -#include "../keyboard.h" -#include "../mem.h" -#include "../rom.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../disk/hdc.h" -#include "../video/video.h" -#include "../video/vid_et4000.h" -#include "../video/vid_oak_oti.h" -#include "../video/vid_paradise.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "device.h" +#include "chipset.h" +#include "keyboard.h" +#include "mem.h" +#include "rom.h" +#include "fdd.h" +#include "fdc.h" +#include "hdc.h" +#include "video.h" #include "machine.h" @@ -123,58 +120,41 @@ machine_at_ama932j_init(const machine_t *model) } int -machine_at_headlandpho_init(const machine_t *model) +machine_at_px286_init(const machine_t *model) { int ret; - ret = bios_load_interleaved(L"roms/machines/headlandpho/286-Headland-LO.BIN", - L"roms/machines/headlandpho/286-Headland-HI.BIN", + ret = bios_load_interleaved(L"roms/machines/px286/286-Headland-LO.BIN", + L"roms/machines/px286/286-Headland-HI.BIN", 0x000f0000, 131072, 0); if (bios_only || !ret) return ret; machine_at_common_ide_init(model); - - machine_at_headland_common_init(1); + device_add(&keyboard_at_device); + device_add(&fdc_at_device); + device_add(&headland_device); return ret; } int -machine_at_headlandquadtel_init(const machine_t *model) +machine_at_quadt286_init(const machine_t *model) { int ret; - ret = bios_load_interleaved(L"roms/machines/headlandquadtel/Amiht-l.BIN", - L"roms/machines/headlandquadtel/AMIHT-H.BIN", - 0x000f0000, 131072, 0); + ret = bios_load_interleaved(L"roms/machines/quadt286/QUADT89L.ROM", + L"roms/machines/quadt286/QUADT89H.ROM", + 0x000f0000, 65536, 0); if (bios_only || !ret) return ret; machine_at_common_ide_init(model); - - machine_at_headland_common_init(1); - - return ret; -} - -int -machine_at_iqs_init(const machine_t *model) -{ - int ret; - - ret = bios_load_interleaved(L"roms/machines/iqs/286-Headland-IQS-LO.BIN", - L"roms/machines/iqs/286-Headland-IQS-HI.BIN", - 0x000f0000, 131072, 0); - - if (bios_only || !ret) - return ret; - - machine_at_common_ide_init(model); - - machine_at_headland_common_init(1); + device_add(&keyboard_at_device); + device_add(&fdc_at_device); + device_add(&headland_device); return ret; } @@ -220,14 +200,33 @@ machine_at_neat_ami_init(const machine_t *model) return ret; } -#if defined(DEV_BRANCH) && defined(USE_MICRONICS386) int -machine_at_micronics386_init(const machine_t *model) +machine_at_goldstar386_init(const machine_t *model) { int ret; - ret = bios_load_interleaved(L"roms/machines/micronics386/386-Micronics 09-00021-LO.BIN", - L"roms/machines/micronics386/386-Micronics 09-00021-HI.BIN", + ret = bios_load_interleaved(L"roms/machines/goldstar386/386-Goldstar-E.BIN", + L"roms/machines/goldstar386/386-Goldstar-O.BIN", + 0x000f0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_init(model); + + device_add(&neat_device); + device_add(&fdc_at_device); + + return ret; +} + +int +machine_at_micronics386_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/micronics386/386-Micronics-09-00021-EVEN.BIN", + L"roms/machines/micronics386/386-Micronics-09-00021-ODD.BIN", 0x000f0000, 131072, 0); if (bios_only || !ret) @@ -240,7 +239,6 @@ machine_at_micronics386_init(const machine_t *model) return ret; } -#endif static void machine_at_scat_init(const machine_t *model, int is_v4) @@ -408,3 +406,33 @@ machine_at_wd76c10_init(const machine_t *model) return ret; } + +const device_t * +at_commodore_sl386sx_get_device(void) +{ + return &gd5402_onboard_device; +} + +int +machine_at_commodore_sl386sx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_interleaved(L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-lo-v1.04-390914-04.bin", + L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-hi-v1.04-390915-04.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_ide_init(model); + + device_add(&keyboard_at_device); + device_add(&fdc_at_device); + device_add(&vlsi_scamp_device); + + if (gfxcard == VID_INTERNAL) + device_add(&gd5402_onboard_device); + + return ret; +} diff --git a/src/machine/m_at_386dx_486.c b/src/machine/m_at_386dx_486.c index a9b913b5a..78562d82f 100644 --- a/src/machine/m_at_386dx_486.c +++ b/src/machine/m_at_386dx_486.c @@ -8,13 +8,13 @@ * * Implementation of 386DX and 486 machines. * - * Version: @(#)m_at_386dx_486.c 1.0.0 2019/05/16 + * Version: @(#)m_at_386dx_486.c 1.0.2 2020/01/20 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2010-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -22,24 +22,24 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../device.h" -#include "../chipset/chipset.h" -#include "../keyboard.h" -#include "../mem.h" -#include "../pci.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../rom.h" -#include "../sio.h" -#include "../disk/hdc.h" -#include "../video/video.h" -#include "../video/vid_ht216.h" -#include "../intel_flash.h" -#include "../intel_sio.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "device.h" +#include "chipset.h" +#include "keyboard.h" +#include "mem.h" +#include "nvr.h" +#include "pci.h" +#include "fdd.h" +#include "fdc.h" +#include "rom.h" +#include "sio.h" +#include "hdc.h" +#include "video.h" +#include "intel_flash.h" +#include "intel_sio.h" #include "machine.h" @@ -253,7 +253,7 @@ machine_at_win471_init(const machine_t *model) { int ret; - ret = bios_load_linear(L"roms/machines/win471/4sim001.bin", + ret = bios_load_linear(L"roms/machines/win471/486-SiS_AC0360136.BIN", 0x000f0000, 65536, 0); if (bios_only || !ret) @@ -269,17 +269,13 @@ machine_at_win471_init(const machine_t *model) static void machine_at_sis_85c496_common_init(const machine_t *model) { - machine_at_common_init(model); - - device_add(&ide_pci_device); + device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x05, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x05, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0B, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); - device_add(&keyboard_ps2_pci_device); pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); @@ -301,9 +297,60 @@ machine_at_r418_init(const machine_t *model) if (bios_only || !ret) return ret; + machine_at_common_init(model); + machine_at_sis_85c496_common_init(model); + pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); device_add(&fdc37c665_device); + device_add(&keyboard_ps2_pci_device); + + return ret; +} + + +int +machine_at_ls486e_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ls486e/LS486E RevC.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + device_add(&ls486e_nvr_device); + + machine_at_sis_85c496_common_init(model); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&fdc37c665_device); + device_add(&keyboard_ps2_ami_pci_device); + + return ret; +} + + +int +machine_at_4dps_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/4dps/4DPS172G.BIN", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + machine_at_sis_85c496_common_init(model); + pci_register_slot(0x07, PCI_CARD_NORMAL, 4, 1, 2, 3); + + device_add(&w83787f_device); + device_add(&keyboard_ps2_pci_device); return ret; } @@ -324,12 +371,12 @@ machine_at_alfredo_init(const machine_t *model) device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); device_add(&sio_device); device_add(&fdc37c663_device); @@ -339,3 +386,35 @@ machine_at_alfredo_init(const machine_t *model) return ret; } + + +int +machine_at_486sp3g_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/486sp3g/PCI-I-486SP3G_0306.001 (Beta).bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + device_add(&ide_pci_2ch_device); + + pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); + pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&keyboard_ps2_pci_device); + device_add(&sio_device); /* Site says it has a ZB, but the BIOS is designed for an IB. */ + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + device_add(&i420zx_device); + + return ret; +} diff --git a/src/machine/m_at_commodore.c b/src/machine/m_at_commodore.c index 348c43e36..066a8ab7a 100644 --- a/src/machine/m_at_commodore.c +++ b/src/machine/m_at_commodore.c @@ -40,16 +40,16 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../io.h" -#include "../mem.h" -#include "../lpt.h" -#include "../rom.h" -#include "../serial.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "86box_io.h" +#include "mem.h" +#include "lpt.h" +#include "rom.h" +#include "serial.h" +#include "fdd.h" +#include "fdc.h" #include "machine.h" diff --git a/src/machine/m_at_compaq.c b/src/machine/m_at_compaq.c index 801de3412..ac8175b27 100644 --- a/src/machine/m_at_compaq.c +++ b/src/machine/m_at_compaq.c @@ -21,16 +21,16 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "hdc.h" +#include "hdc_ide.h" #include "machine.h" diff --git a/src/machine/m_at_socket4_5.c b/src/machine/m_at_socket4_5.c index de6312eeb..15012e856 100644 --- a/src/machine/m_at_socket4_5.c +++ b/src/machine/m_at_socket4_5.c @@ -21,26 +21,24 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" -#include "../io.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../chipset/chipset.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../timer.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../keyboard.h" -#include "../intel_flash.h" -#include "../intel_sio.h" -#include "../piix.h" -#include "../sio.h" -#include "../video/video.h" -#include "../video/vid_cl54xx.h" -#include "../video/vid_s3.h" +#include "86box.h" +#include "mem.h" +#include "86box_io.h" +#include "rom.h" +#include "pci.h" +#include "device.h" +#include "chipset.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "timer.h" +#include "fdd.h" +#include "fdc.h" +#include "keyboard.h" +#include "intel_flash.h" +#include "intel_sio.h" +#include "piix.h" +#include "sio.h" +#include "video.h" #include "machine.h" @@ -51,12 +49,12 @@ machine_at_premiere_common_init(const machine_t *model) device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 2, 1, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 3, 2, 4); - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); device_add(&sio_zb_device); device_add(&fdc37c665_device); @@ -71,14 +69,14 @@ machine_at_award_common_init(const machine_t *model) device_add(&ide_pci_2ch_device); pci_init(PCI_CONFIG_TYPE_2 | PCI_NO_IRQ_STEERING); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x01, PCI_CARD_SPECIAL, 0, 0, 0, 0); pci_register_slot(0x03, PCI_CARD_NORMAL, 1, 2, 3, 4); /* 03 = Slot 1 */ pci_register_slot(0x04, PCI_CARD_NORMAL, 2, 3, 4, 1); /* 04 = Slot 2 */ pci_register_slot(0x05, PCI_CARD_NORMAL, 3, 4, 1, 2); /* 05 = Slot 3 */ pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); /* 06 = Slot 4 */ pci_register_slot(0x07, PCI_CARD_SCSI, 1, 2, 3, 4); /* 07 = SCSI */ - pci_register_slot(0x02, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&fdc_at_device); device_add(&keyboard_ps2_pci_device); device_add(&sio_device); @@ -104,6 +102,7 @@ machine_at_batman_init(const machine_t *model) return ret; } + int machine_at_ambradp60_init(const machine_t *model) { @@ -122,6 +121,28 @@ machine_at_ambradp60_init(const machine_t *model) return ret; } + +#if defined(DEV_BRANCH) && defined(USE_VPP60) +int +machine_at_valuepointp60_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear_combined(L"roms/machines/valuepointp60/1006AV0M.BIO", + L"roms/machines/valuepointp60/1006AV0M.BI1", 0x1d000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_premiere_common_init(model); + + device_add(&i430lx_device); + + return ret; +} +#endif + + int machine_at_586mc1_init(const machine_t *model) { @@ -159,6 +180,7 @@ machine_at_plato_init(const machine_t *model) return ret; } + int machine_at_ambradp90_init(const machine_t *model) { @@ -177,6 +199,7 @@ machine_at_ambradp90_init(const machine_t *model) return ret; } + int machine_at_430nx_init(const machine_t *model) { @@ -211,12 +234,12 @@ machine_at_p54tp4xe_init(const machine_t *model) /* Award BIOS, SMC FDC37C665. */ pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_pci_device); device_add(&i430fx_device); device_add(&piix_device); @@ -241,13 +264,13 @@ machine_at_endeavor_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); if (gfxcard == VID_INTERNAL) device_add(&s3_phoenix_trio64_onboard_pci_device); @@ -283,11 +306,11 @@ machine_at_zappa_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0F, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); @@ -312,12 +335,12 @@ machine_at_mb500n_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x14, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x12, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x11, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_pci_device); device_add(&i430fx_device); device_add(&piix_device); @@ -342,12 +365,12 @@ machine_at_president_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430fx_device); device_add(&piix_device); device_add(&keyboard_ps2_pci_device); @@ -373,12 +396,12 @@ machine_at_vectra54_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&keyboard_ps2_ami_pci_device); device_add(&i430fx_device); device_add(&piix_device); diff --git a/src/machine/m_at_socket7_s7.c b/src/machine/m_at_socket7_s7.c index 377a37bd5..f48db0542 100644 --- a/src/machine/m_at_socket7_s7.c +++ b/src/machine/m_at_socket7_s7.c @@ -8,36 +8,38 @@ * * Implementation of Socket 7 and Super Socket 7 machines. * - * Version: @(#)m_at_socket7_s7.c 1.0.1 2019/10/20 + * Version: @(#)m_at_socket7_s7.c 1.0.3 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, + * Melissa Goad, * - * Copyright 2010-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2010-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. */ #include #include #include #include #include -#include "../86box.h" -#include "../mem.h" -#include "../io.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../chipset/chipset.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../keyboard.h" -#include "../intel_flash.h" -#include "../intel_sio.h" -#include "../piix.h" -#include "../sio.h" -#include "../video/video.h" -#include "../video/vid_cl54xx.h" -#include "../video/vid_s3.h" +#include "86box.h" +#include "mem.h" +#include "io.h" +#include "rom.h" +#include "pci.h" +#include "device.h" +#include "chipset.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "keyboard.h" +#include "intel_flash.h" +#include "intel_sio.h" +#include "piix.h" +#include "sio.h" +#include "sst_flash.h" +#include "via_vt82c586b.h" +#include "video.h" #include "machine.h" @@ -47,13 +49,13 @@ machine_at_thor_common_init(const machine_t *model, int mr) machine_at_common_init_ex(model, mr); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 2, 1); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 3, 2, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430fx_device); device_add(&piix_device); device_add(&keyboard_ps2_ami_pci_device); @@ -112,14 +114,14 @@ machine_at_pb640_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 1, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 2, 1, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430fx_pb640_device); - device_add(&piix_pb640_device); + device_add(&piix_device); device_add(&ide_isa_2ch_device); if (gfxcard == VID_INTERNAL) @@ -154,8 +156,8 @@ machine_at_acerm3a_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0E, PCI_CARD_NORMAL, 3, 4, 1, 2); @@ -187,8 +189,8 @@ machine_at_acerv35n_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); @@ -220,12 +222,12 @@ machine_at_ap53_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x14, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x06, PCI_CARD_ONBOARD, 1, 2, 3, 4); device_add(&i430hx_device); device_add(&piix3_device); @@ -251,12 +253,12 @@ machine_at_p55t2p4_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -281,12 +283,12 @@ machine_at_p55t2s_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -316,13 +318,48 @@ machine_at_tc430hx_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0E, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0F, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x10, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + device_add(&i430hx_device); + device_add(&piix3_device); + device_add(&keyboard_ps2_ami_pci_device); + device_add(&pc87306_device); + device_add(&intel_flash_bxt_ami_device); + + return ret; +} + + +int +machine_at_equium5200_init(const machine_t *model) // Information about that machine on machine.h +{ + int ret; + + ret = bios_load_linear_combined2(L"roms/machines/equium5200/1003DK08.BIO", + L"roms/machines/equium5200/1003DK08.BI1", + L"roms/machines/equium5200/1003DK08.BI2", + L"roms/machines/equium5200/1003DK08.BI3", + L"roms/machines/equium5200/1003DK08.RCV", + 0x3a000, 128); + + if (bios_only || !ret) + return ret; + + machine_at_common_init(model); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_ONBOARD, 4, 0, 0, 0); + pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x13, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 0, 0, 0); // riser device_add(&i430hx_device); device_add(&piix3_device); device_add(&keyboard_ps2_ami_pci_device); @@ -331,6 +368,7 @@ machine_at_tc430hx_init(const machine_t *model) return ret; } + #endif @@ -348,12 +386,12 @@ machine_at_p55tvp4_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -378,12 +416,12 @@ machine_at_i430vx_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x12, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x14, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x13, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -408,12 +446,12 @@ machine_at_p55va_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -438,11 +476,11 @@ machine_at_j656vxd_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i430vx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -451,3 +489,157 @@ machine_at_j656vxd_init(const machine_t *model) return ret; } + + +int +machine_at_5tx52_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/5tx52/5itw002.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 4); /* PIIX4 */ + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877tf_acorp_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_txp4_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/txp4/0112L.001", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977tf_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_ym430tx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ym430tx/YM430TX.003", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x01, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977tf_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_sp586tx_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/sp586tx/Txa6-32gb.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); /* PIIX4 */ + device_add(&i430tx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977tf_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_mvp3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/ficva503p/je4333.bin", + 0x000e0000, 131072, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0a, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + device_add(&via_mvp3_device); + device_add(&via_vt82c586b_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877tf_device); + device_add(&sst_flash_39sf010_device); + + return ret; +} diff --git a/src/machine/m_at_socket8.c b/src/machine/m_at_socket8.c index 18e4355c0..d6f590d7b 100644 --- a/src/machine/m_at_socket8.c +++ b/src/machine/m_at_socket8.c @@ -6,7 +6,7 @@ * * This file is part of the 86Box distribution. * - * Implementation of Socket 8 machines. + * Implementation of Socket 8 and Slot 1 machines. * * Version: @(#)m_at_socket8.c 1.0.0 2019/05/16 * @@ -19,23 +19,24 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" -#include "../io.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../chipset/chipset.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../keyboard.h" -#include "../intel_flash.h" -#include "../intel_sio.h" -#include "../piix.h" -#include "../sio.h" -#include "../video/video.h" -#include "../video/vid_cl54xx.h" -#include "../video/vid_s3.h" +#include "86box.h" +#include "mem.h" +#include "86box_io.h" +#include "rom.h" +#include "pci.h" +#include "device.h" +#include "chipset.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "keyboard.h" +#include "intel_flash.h" +#include "intel_sio.h" +#include "piix.h" +#include "sio.h" +#include "sst_flash.h" +#include "hwm.h" +#include "video.h" +#include "cpu.h" #include "machine.h" @@ -56,13 +57,13 @@ machine_at_i440fx_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); pci_register_slot(0x0A, PCI_CARD_NORMAL, 1, 2, 3, 4); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); device_add(&i440fx_device); device_add(&piix3_device); device_add(&keyboard_ps2_pci_device); @@ -87,8 +88,8 @@ machine_at_s1668_init(const machine_t *model) machine_at_common_init(model); pci_init(PCI_CONFIG_TYPE_1); - pci_register_slot(0x00, PCI_CARD_SPECIAL, 0, 0, 0, 0); - pci_register_slot(0x07, PCI_CARD_SPECIAL, 0, 0, 0, 0); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0); pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4); pci_register_slot(0x0D, PCI_CARD_NORMAL, 2, 3, 4, 1); pci_register_slot(0x0C, PCI_CARD_NORMAL, 3, 4, 1, 2); @@ -103,5 +104,163 @@ machine_at_s1668_init(const machine_t *model) return ret; } - +#endif +int +machine_at_6abx3_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/6abx3/6abx3h1.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83877tf_device); + // device_add(&w83977tf_device); + // device_add(&intel_flash_bxt_device); + // device_add(&sst_flash_29ee020_device); + device_add(&intel_flash_bxt_device); + + return ret; +} +#if defined(DEV_BRANCH) && defined(USE_I686) +int +machine_at_p2bls_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/p2bls/1014ls.003", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x06, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x07, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x04, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4_device); + device_add(&keyboard_ps2_pci_device); + device_add(&w83977ef_device); + device_add(&sst_flash_39sf020_device); + + hwm_values_t machine_hwm = { + { /* fan speeds */ + 3000, /* Chassis */ + 3000, /* CPU */ + 3000, /* Power */ + 0 + }, { /* temperatures */ + 30, /* MB */ + 0, /* unused */ + 27, /* CPU */ + 0 + }, { /* voltages (divisors other than 16 = unclear how that number was achieved) */ + 2050 / 16, /* VCORE (2.05V by default) */ + 0, /* unused */ + 3300 / 16, /* +3.3V */ + 5000 / 27, /* +5V */ + VDIV(12000, 28, 10) / 16, /* +12V (with 28K/10K resistor divider suggested in the W83781D datasheet) */ + 12000 / 55, /* -12V */ + 5000 / 24, /* -5V */ + 0 + } + }; + if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2) + machine_hwm.voltages[0] = 2800 / 16; /* set higher VCORE (2.8V) for Klamath */ + hwm_set_values(machine_hwm); + device_add(&as99127f_device); + + return ret; +} + + +int +machine_at_p6bxt_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear(L"roms/machines/p6bxt/bxt53s.BIN", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 3, 2, 1); /* Slot 5: Probably the integrated sound chip. */ + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440bx_device); + device_add(&piix4e_device); + device_add(&w83977tf_device); + device_add(&keyboard_ps2_pci_device); + device_add(&intel_flash_bxt_device); + + return ret; +} + + +int +machine_at_63a_init(const machine_t *model) +{ + + /* 440ZX Board. 440ZX is basically an underpowered 440BX. There no + difference between to chipsets other than the name. */ + int ret; + + ret = bios_load_linear(L"roms/machines/63a/63a-q3.bin", + 0x000c0000, 262144, 0); + + if (bios_only || !ret) + return ret; + + machine_at_common_init_ex(model, 2); + + pci_init(PCI_CONFIG_TYPE_1); + pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0); + pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4); + pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1); + pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2); + pci_register_slot(0x0B, PCI_CARD_NORMAL, 4, 1, 2, 3); + pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4); // Integrated Sound? + pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4); + pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4); + device_add(&i440zx_device); + device_add(&piix4e_device); + device_add(&w83977tf_device); + device_add(&keyboard_ps2_pci_device); + device_add(&intel_flash_bxt_device); + + return ret; +} #endif diff --git a/src/machine/m_at_t3100e.c b/src/machine/m_at_t3100e.c index 8f69fc951..4244a96e5 100644 --- a/src/machine/m_at_t3100e.c +++ b/src/machine/m_at_t3100e.c @@ -152,17 +152,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../io.h" -#include "../mouse.h" -#include "../mem.h" -#include "../device.h" -#include "../keyboard.h" -#include "../rom.h" -#include "../cpu/cpu.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" +#include "86box.h" +#include "timer.h" +#include "86box_io.h" +#include "mouse.h" +#include "mem.h" +#include "device.h" +#include "keyboard.h" +#include "rom.h" +#include "cpu.h" +#include "fdd.h" +#include "fdc.h" #include "machine.h" #include "m_at_t3100e.h" @@ -571,8 +571,13 @@ uint8_t t3100e_ems_in(uint16_t addr, void *p) { struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; - return regs->page[port_to_page(addr)]; - + int page = port_to_page(addr); + if (page >= 0) + return regs->page[page]; + else { + fatal("t3100e_ems_in(): invalid address"); + return 0xff; + } } /* Write EMS page register */ @@ -581,6 +586,9 @@ void t3100e_ems_out(uint16_t addr, uint8_t val, void *p) struct t3100e_ems_regs *regs = (struct t3100e_ems_regs *)p; int pg = port_to_page(addr); + if (pg == -1) + return; + regs->page_exec[pg & 3] = t3100e_ems_execaddr(regs, pg, val); t3100e_log("EMS: page %d %02x -> %02x [%06x]\n", pg, regs->page[pg], val, regs->page_exec[pg & 3]); diff --git a/src/machine/m_at_t3100e_vid.c b/src/machine/m_at_t3100e_vid.c index 683789a20..6f9f20200 100644 --- a/src/machine/m_at_t3100e_vid.c +++ b/src/machine/m_at_t3100e_vid.c @@ -57,14 +57,14 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../cpu/cpu.h" -#include "../video/video.h" -#include "../video/vid_cga.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "mem.h" +#include "timer.h" +#include "cpu.h" +#include "video.h" +#include "vid_cga.h" #include "m_at_t3100e.h" diff --git a/src/machine/m_europc.c b/src/machine/m_europc.c index 04e464726..d642b0099 100644 --- a/src/machine/m_europc.c +++ b/src/machine/m_europc.c @@ -87,22 +87,22 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../nmi.h" -#include "../mem.h" -#include "../pit.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../game/gameport.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../disk/hdc.h" -#include "../video/video.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "nmi.h" +#include "mem.h" +#include "pit.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "keyboard.h" +#include "mouse.h" +#include "gameport.h" +#include "fdd.h" +#include "fdc.h" +#include "hdc.h" +#include "video.h" #include "machine.h" @@ -615,7 +615,7 @@ europc_boot(const device_t *info) mouse_bus_set_irq(sys->mouse, 2); /* Configure the port for (Bus Mouse Compatible) Mouse. */ b |= 0x01; - } else if (joystick_type != 7) + } else if (joystick_type != JOYSTICK_TYPE_NONE) b |= 0x02; /* enable port as joysticks */ sys->nvr.regs[MRTC_CONF_C] = b; diff --git a/src/machine/m_olivetti_m24.c b/src/machine/m_olivetti_m24.c index 694fec24c..f2fef9bb8 100644 --- a/src/machine/m_olivetti_m24.c +++ b/src/machine/m_olivetti_m24.c @@ -24,25 +24,25 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" -#include "../io.h" -#include "../pic.h" -#include "../pit.h" -#include "../ppi.h" -#include "../nmi.h" -#include "../mem.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../rom.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../sound/sound.h" -#include "../sound/snd_speaker.h" -#include "../video/video.h" +#include "86box.h" +#include "timer.h" +#include "86box_io.h" +#include "pic.h" +#include "pit.h" +#include "ppi.h" +#include "nmi.h" +#include "mem.h" +#include "device.h" +#include "nvr.h" +#include "keyboard.h" +#include "mouse.h" +#include "rom.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "sound.h" +#include "snd_speaker.h" +#include "video.h" #include "machine.h" @@ -892,7 +892,7 @@ machine_olim24_init(const machine_t *model) keyboard_set_table(scancode_xt); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); /* FIXME: make sure this is correct?? */ diff --git a/src/machine/m_pcjr.c b/src/machine/m_pcjr.c index a5ff9cc8b..77628a800 100644 --- a/src/machine/m_pcjr.c +++ b/src/machine/m_pcjr.c @@ -26,25 +26,25 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../device.h" -#include "../serial.h" -#include "../keyboard.h" -#include "../rom.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../sound/sound.h" -#include "../sound/snd_speaker.h" -#include "../sound/snd_sn76489.h" -#include "../video/video.h" -#include "../video/vid_cga_comp.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "nmi.h" +#include "pic.h" +#include "pit.h" +#include "mem.h" +#include "device.h" +#include "serial.h" +#include "keyboard.h" +#include "rom.h" +#include "fdd.h" +#include "fdc.h" +#include "sound.h" +#include "snd_speaker.h" +#include "snd_sn76489.h" +#include "video.h" +#include "vid_cga_comp.h" #include "machine.h" diff --git a/src/machine/m_ps1.c b/src/machine/m_ps1.c index 2bfd6e7f7..c8a3ee8b2 100644 --- a/src/machine/m_ps1.c +++ b/src/machine/m_ps1.c @@ -37,31 +37,29 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../nmi.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../game/gameport.h" -#include "../lpt.h" -#include "../serial.h" -#include "../keyboard.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../sound/sound.h" -#include "../sound/snd_sn76489.h" -#include "../video/video.h" -#include "../video/vid_vga.h" -#include "../video/vid_ti_cf62011.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "pit.h" +#include "mem.h" +#include "nmi.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "gameport.h" +#include "lpt.h" +#include "serial.h" +#include "keyboard.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" +#include "sound.h" +#include "snd_sn76489.h" +#include "video.h" #include "machine.h" @@ -459,12 +457,6 @@ ps1_setup(int model) lpt2_remove(); - /* Enable the PS/1 VGA controller. */ - if (model == 2011) - device_add(&ps1vga_device); - else - device_add(&ibm_ps1_2121_device); - device_add(&snd_device); device_add(&fdc_at_actlow_device); @@ -505,6 +497,12 @@ ps1_setup(int model) device_add(&ide_isa_device); } #endif + + /* Enable the PS/1 VGA controller. */ + if (model == 2011) + device_add(&ps1vga_device); + else + device_add(&ibm_ps1_2121_device); } @@ -525,7 +523,7 @@ ps1_common_init(const machine_t *model) device_add(&keyboard_ps2_ps1_device); /* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */ - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_201_device); } diff --git a/src/machine/m_ps1_hdc.c b/src/machine/m_ps1_hdc.c index 5c10ca69b..d767b7aa8 100644 --- a/src/machine/m_ps1_hdc.c +++ b/src/machine/m_ps1_hdc.c @@ -92,16 +92,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../device.h" -#include "../disk/hdc.h" -#include "../disk/hdd.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "timer.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "device.h" +#include "hdc.h" +#include "hdd.h" +#include "plat.h" +#include "ui.h" #include "machine.h" diff --git a/src/machine/m_ps2_isa.c b/src/machine/m_ps2_isa.c index a713278d9..fe6d3e6c4 100644 --- a/src/machine/m_ps2_isa.c +++ b/src/machine/m_ps2_isa.c @@ -2,25 +2,25 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../port_92.h" -#include "../serial.h" -#include "../disk/hdc.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../video/vid_vga.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "keyboard.h" +#include "lpt.h" +#include "port_92.h" +#include "serial.h" +#include "hdc.h" +#include "fdd.h" +#include "fdc.h" +#include "video.h" #include "machine.h" diff --git a/src/machine/m_ps2_mca.c b/src/machine/m_ps2_mca.c index 7eb011931..c4b755a6d 100644 --- a/src/machine/m_ps2_mca.c +++ b/src/machine/m_ps2_mca.c @@ -42,35 +42,29 @@ #include #include #define HAVE_STDARG_H -#include "../86box.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 "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../pit.h" -#include "../mca.h" -#include "../mem.h" -#include "../nmi.h" -#include "../rom.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../nvr.h" -#include "../nvr_ps2.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../mouse.h" -#include "../port_92.h" -#include "../serial.h" -#include "../video/video.h" -#include "../video/vid_vga.h" +#include "86box.h" +#include "cpu.h" +#include "x86.h" +#include "timer.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "pit.h" +#include "mca.h" +#include "mem.h" +#include "nmi.h" +#include "rom.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "nvr.h" +#include "nvr_ps2.h" +#include "keyboard.h" +#include "lpt.h" +#include "mouse.h" +#include "port_92.h" +#include "serial.h" +#include "video.h" #include "machine.h" diff --git a/src/machine/m_tandy.c b/src/machine/m_tandy.c index 3dbc65748..658f8c1f0 100644 --- a/src/machine/m_tandy.c +++ b/src/machine/m_tandy.c @@ -24,24 +24,23 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../io.h" -#include "../pit.h" -#include "../nmi.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../sound/sound.h" -#include "../sound/snd_pssj.h" -#include "../sound/snd_sn76489.h" -#include "../video/video.h" -#include "../video/vid_cga_comp.h" +#include "86box.h" +#include "timer.h" +#include "86box_io.h" +#include "pit.h" +#include "nmi.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "keyboard.h" +#include "sound.h" +#include "snd_sn76489.h" +#include "video.h" +#include "vid_cga_comp.h" #include "machine.h" @@ -1293,7 +1292,8 @@ eep_init(const device_t *info) f = nvr_fopen(eep->path, L"rb"); if (f != NULL) { - fread(eep->store, 128, 1, f); + if (fread(eep->store, 1, 128, f) != 128) + fatal("eep_init(): Error reading Tandy EEPROM\n"); (void)fclose(f); } @@ -1526,7 +1526,7 @@ machine_tandy1k_init(const machine_t *model, int type) device_add(&eep_1000sl2_device); } - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); eep_data_out = 0x0000; diff --git a/src/machine/m_xt.c b/src/machine/m_xt.c index 22a01c882..ec9cd1da6 100644 --- a/src/machine/m_xt.c +++ b/src/machine/m_xt.c @@ -2,18 +2,18 @@ #include #include #include -#include "../86box.h" -#include "../nmi.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../ibm_5161.h" -#include "../keyboard.h" -#include "../rom.h" +#include "86box.h" +#include "nmi.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "ibm_5161.h" +#include "keyboard.h" +#include "rom.h" #include "machine.h" @@ -26,7 +26,7 @@ machine_xt_common_init(const machine_t *model) device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); } @@ -157,10 +157,10 @@ machine_xt86_init(const machine_t *model) ret = bios_load_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", 0x000fe000, 65536, 0x6000); if (ret) { - bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", - 0x000f8000, 24576, 0); - bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", - 0x000f0000, 32768, 0); + (void) bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U18_59X7268_62X0890_27256_F800.BIN", + 0x000f8000, 24576, 0); + (void) bios_load_aux_linear(L"roms/machines/ibmxt86/BIOS_5160_09MAY86_U19_62X0819_68X4370_27256_F000.BIN", + 0x000f0000, 32768, 0); } if (bios_only || !ret) diff --git a/src/machine/m_xt_compaq.c b/src/machine/m_xt_compaq.c index 6af9079fa..edc3cf007 100644 --- a/src/machine/m_xt_compaq.c +++ b/src/machine/m_xt_compaq.c @@ -21,19 +21,19 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../nmi.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../lpt.h" +#include "86box.h" +#include "cpu.h" +#include "nmi.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "keyboard.h" +#include "lpt.h" #include "machine.h" @@ -55,7 +55,7 @@ machine_xt_compaq_init(const machine_t *model) device_add(&keyboard_xt_compaq_device); device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); lpt1_remove(); diff --git a/src/machine/m_xt_laserxt.c b/src/machine/m_xt_laserxt.c index 0b06a238b..41416769c 100644 --- a/src/machine/m_xt_laserxt.c +++ b/src/machine/m_xt_laserxt.c @@ -3,21 +3,21 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../nmi.h" -#include "../timer.h" -#include "../pit.h" -#include "../rom.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "mem.h" +#include "nmi.h" +#include "timer.h" +#include "pit.h" +#include "rom.h" #include "machine.h" -#include "../device.h" -#include "../timer.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../keyboard.h" +#include "device.h" +#include "timer.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "keyboard.h" static int laserxt_emspage[4]; @@ -171,7 +171,7 @@ machine_xt_lxt3_init(const machine_t *model) device_add(&keyboard_xt_lxt3_device); device_add(&fdc_xt_device); nmi_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); laserxt_init(1); diff --git a/src/machine/m_xt_t1000.c b/src/machine/m_xt_t1000.c index 3471b0c12..2e8fd40f9 100644 --- a/src/machine/m_xt_t1000.c +++ b/src/machine/m_xt_t1000.c @@ -87,24 +87,24 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../nmi.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../mem.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../video/video.h" -#include "../plat.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "nmi.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "keyboard.h" +#include "lpt.h" +#include "mem.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "video.h" +#include "plat.h" #include "machine.h" #include "m_xt_t1000.h" @@ -240,6 +240,7 @@ tc8521_time_get(uint8_t *regs, struct tm *tm) tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); //FIXME: wday + tm->tm_wday = 1; /* Dummy value so it is not uninitialized. */ tm->tm_mday = nibbles(TC8521_DAY); tm->tm_mon = (nibbles(TC8521_MONTH) - 1); tm->tm_year = (nibbles(TC8521_YEAR) + 1980); @@ -881,7 +882,8 @@ machine_xt_t1000_init(const machine_t *model) t1000.romdrive = malloc(T1000_ROMSIZE); if (t1000.romdrive) { memset(t1000.romdrive, 0xff, T1000_ROMSIZE); - fread(t1000.romdrive, T1000_ROMSIZE, 1, f); + if (fread(t1000.romdrive, 1, T1000_ROMSIZE, f) != T1000_ROMSIZE) + fatal("machine_xt_t1000_init(): Error reading DOS ROM data\n"); } fclose(f); } @@ -1015,11 +1017,14 @@ static void t1000_configsys_load(void) { FILE *f; + int size; memset(t1000.t1000_nvram, 0x1a, sizeof(t1000.t1000_nvram)); f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"rb"); if (f != NULL) { - fread(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); + size = sizeof(t1000.t1000_nvram); + if (fread(t1000.t1000_nvram, size, 1, f) != size) + fatal("t1000_configsys_load(): Error reading data\n"); fclose(f); } } @@ -1029,10 +1034,13 @@ static void t1000_configsys_save(void) { FILE *f; + int size; f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"wb"); if (f != NULL) { - fwrite(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); + size = sizeof(t1000.t1000_nvram); + if (fwrite(t1000.t1000_nvram, 1, size, f) != size) + fatal("t1000_configsys_save(): Error writing data\n"); fclose(f); } } @@ -1042,11 +1050,14 @@ static void t1200_state_load(void) { FILE *f; + int size; memset(t1000.t1200_nvram, 0, sizeof(t1000.t1200_nvram)); f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"rb"); if (f != NULL) { - fread(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); + size = sizeof(t1000.t1200_nvram); + if (fread(t1000.t1200_nvram, 1, size, f) != size) + fatal("t1200_state_load(): Error reading data\n"); fclose(f); } } @@ -1056,10 +1067,13 @@ static void t1200_state_save(void) { FILE *f; + int size; f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"wb"); if (f != NULL) { - fwrite(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); + size = sizeof(t1000.t1200_nvram); + if (fwrite(t1000.t1200_nvram, 1, size, f) != size) + fatal("t1200_state_save(): Error writing data\n"); fclose(f); } } diff --git a/src/machine/m_xt_t1000_vid.c b/src/machine/m_xt_t1000_vid.c index 1e2d62e13..8196e8e59 100644 --- a/src/machine/m_xt_t1000_vid.c +++ b/src/machine/m_xt_t1000_vid.c @@ -42,14 +42,14 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../cpu/cpu.h" -#include "../video/video.h" -#include "../video/vid_cga.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "mem.h" +#include "timer.h" +#include "cpu.h" +#include "video.h" +#include "vid_cga.h" #include "m_xt_t1000.h" diff --git a/src/machine/m_xt_xi8088.c b/src/machine/m_xt_xi8088.c index 101e8a0ae..42b0d2498 100644 --- a/src/machine/m_xt_xi8088.c +++ b/src/machine/m_xt_xi8088.c @@ -2,25 +2,25 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" -#include "../pic.h" -#include "../pit.h" -#include "../dma.h" -#include "../mem.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../nmi.h" -#include "../nvr.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../rom.h" -#include "../disk/hdc.h" -#include "../video/video.h" +#include "86box.h" +#include "timer.h" +#include "pic.h" +#include "pit.h" +#include "dma.h" +#include "mem.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "nmi.h" +#include "nvr.h" +#include "gameport.h" +#include "keyboard.h" +#include "lpt.h" +#include "rom.h" +#include "hdc.h" +#include "video.h" #include "machine.h" -#include "../cpu/cpu.h" +#include "cpu.h" #include "m_xt_xi8088.h" @@ -151,13 +151,15 @@ machine_xt_xi8088_init(const machine_t *model) int ret; if (bios_only) { - ret = bios_load_linear(L"roms/machines/xi8088/bios-xi8088.bin", - 0x000f0000, 65536, 0); + ret = bios_load_linear_inverted(L"roms/machines/xi8088/bios-xi8088-128k.bin", + 0x000e0000, 131072, 0); + ret |= bios_load_linear(L"roms/machines/xi8088/bios-xi8088.bin", + 0x000f0000, 65536, 0); } else { device_add(&xi8088_device); if (xi8088_bios_128kb()) { - ret = bios_load_linear_inverted(L"roms/machines/xi8088/bios-xi8088.bin", + ret = bios_load_linear_inverted(L"roms/machines/xi8088/bios-xi8088-128k.bin", 0x000e0000, 131072, 0); } else { ret = bios_load_linear(L"roms/machines/xi8088/bios-xi8088.bin", @@ -175,7 +177,7 @@ machine_xt_xi8088_init(const machine_t *model) nmi_init(); device_add(&ibmat_nvr_device); pic2_init(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) device_add(&gameport_device); return ret; diff --git a/src/machine/m_xt_zenith.c b/src/machine/m_xt_zenith.c index 23b44199d..d6b1b5261 100644 --- a/src/machine/m_xt_zenith.c +++ b/src/machine/m_xt_zenith.c @@ -24,22 +24,22 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../timer.h" -#include "../dma.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../serial.h" +#include "86box.h" +#include "cpu.h" +#include "timer.h" +#include "dma.h" +#include "nmi.h" +#include "pic.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "fdd.h" +#include "fdc.h" +#include "gameport.h" +#include "keyboard.h" +#include "lpt.h" +#include "serial.h" #include "machine.h" diff --git a/src/machine/machine.c b/src/machine/machine.c index c2f19bd47..d5a5680b1 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -8,15 +8,15 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.c 1.0.38 2019/11/15 + * Version: @(#)machine.c 1.0.39 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -24,18 +24,18 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../dma.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../lpt.h" -#include "../serial.h" -#include "../cpu/cpu.h" -#include "../video/video.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "lpt.h" +#include "serial.h" +#include "cpu.h" +#include "video.h" #include "machine.h" @@ -81,6 +81,8 @@ machine_init_ex(int m) mem_reset(); lpt_init(); + + smbase = 0x30000; } /* All good, boot the machine! */ diff --git a/src/machine/machine.h b/src/machine/machine.h index 7d4b52ab7..0a9bf8b35 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -8,15 +8,15 @@ * * Handling of the emulated machines. * - * Version: @(#)machine.h 1.0.34 2019/03/08 + * Version: @(#)machine.h 1.0.38 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_MACHINE_H # define EMU_MACHINE_H @@ -151,7 +151,7 @@ extern const device_t *pc3086_get_device(void); #endif /* m_at.c */ -extern void machine_at_common_init_ex(const machine_t *, int is_ibm); +extern void machine_at_common_init_ex(const machine_t *, int type); extern void machine_at_common_init(const machine_t *); extern void machine_at_init(const machine_t *); extern void machine_at_ps2_init(const machine_t *); @@ -169,6 +169,10 @@ extern int machine_at_ibmatquadtel_init(const machine_t *); // IBM AT with Quadt extern int machine_at_ibmxt286_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_SIEMENS) +extern int machine_at_siemens_init(const machine_t *); //Siemens PCD-2L. N82330 discrete machine. It segfaults in some places +#endif + #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) extern int machine_at_open_at_init(const machine_t *); #endif @@ -179,15 +183,15 @@ extern int machine_at_headland_init(const machine_t *); #endif extern int machine_at_tg286m_init(const machine_t *); extern int machine_at_ama932j_init(const machine_t *); -extern int machine_at_headlandpho_init(const machine_t *); -extern int machine_at_headlandquadtel_init(const machine_t *); -extern int machine_at_iqs_init(const machine_t *); +extern int machine_at_px286_init(const machine_t *); +extern int machine_at_quadt286_init(const machine_t *); extern int machine_at_neat_init(const machine_t *); extern int machine_at_neat_ami_init(const machine_t *); -#if defined(DEV_BRANCH) && defined(USE_MICRONICS386) -extern int machine_at_micronics386_init(const machine_t *); //Neat based Phoenix 80386 board. It has memory related issues. -#endif + +extern int machine_at_goldstar386_init(const machine_t *); +extern int machine_at_micronics386_init(const machine_t *); + extern int machine_at_award286_init(const machine_t *); extern int machine_at_gw286ct_init(const machine_t *); @@ -197,10 +201,12 @@ extern int machine_at_spc4216p_init(const machine_t *); extern int machine_at_kmxc02_init(const machine_t *); extern int machine_at_deskmaster286_init(const machine_t *); +extern int machine_at_commodore_sl386sx_init(const machine_t *); extern int machine_at_wd76c10_init(const machine_t *); #ifdef EMU_DEVICE_H -extern const device_t *at_ama932j_get_device(void); +extern const device_t *at_ama932j_get_device(void); +extern const device_t *at_commodore_sl386sx_get_device(void); #endif /* m_at_386dx_486.c */ @@ -221,7 +227,10 @@ extern int machine_at_px471_init(const machine_t *); extern int machine_at_win471_init(const machine_t *); extern int machine_at_r418_init(const machine_t *); +extern int machine_at_ls486e_init(const machine_t *); +extern int machine_at_4dps_init(const machine_t *); extern int machine_at_alfredo_init(const machine_t *); +extern int machine_at_486sp3g_init(const machine_t *); /* m_at_commodore.c */ extern int machine_at_cmdpc_init(const machine_t *); @@ -236,6 +245,9 @@ extern int machine_at_portableiii386_init(const machine_t *); /* m_at_socket4_5.c */ extern int machine_at_batman_init(const machine_t *); extern int machine_at_ambradp60_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_VPP60) +extern int machine_at_valuepointp60_init(const machine_t *); +#endif extern int machine_at_586mc1_init(const machine_t *); extern int machine_at_plato_init(const machine_t *); @@ -269,13 +281,21 @@ extern int machine_at_p55t2p4_init(const machine_t *); extern int machine_at_p55t2s_init(const machine_t *); #if defined(DEV_BRANCH) && defined(USE_TC430HX) extern int machine_at_tc430hx_init(const machine_t *); -#endif +extern int machine_at_equium5200_init(const machine_t *); //Toshiba branded CU430HX. Presents same issues as the TC430HX. +#endif //Other than that, works as intended(No need to set an MPU too). extern int machine_at_p55tvp4_init(const machine_t *); extern int machine_at_i430vx_init(const machine_t *); extern int machine_at_p55va_init(const machine_t *); extern int machine_at_j656vxd_init(const machine_t *); +extern int machine_at_5tx52_init(const machine_t *); +extern int machine_at_txp4_init(const machine_t *); +extern int machine_at_ym430tx_init(const machine_t *); +extern int machine_at_sp586tx_init(const machine_t *); + +extern int machine_at_mvp3_init(const machine_t *); + #ifdef EMU_DEVICE_H extern const device_t *at_pb640_get_device(void); #endif @@ -286,6 +306,13 @@ extern int machine_at_i440fx_init(const machine_t *); extern int machine_at_s1668_init(const machine_t *); #endif +extern int machine_at_6abx3_init(const machine_t *); +#if defined(DEV_BRANCH) && defined(USE_I686) /*P2B-LS has no VIA C3 BIOS support, so further investigation may be needed*/ +extern int machine_at_p2bls_init(const machine_t *); +extern int machine_at_p6bxt_init(const machine_t *); +extern int machine_at_63a_init(const machine_t *); +#endif + /* m_at_t3100e.c */ extern int machine_at_t3100e_init(const machine_t *); diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 893b37e7a..c3e4c4959 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -11,28 +11,34 @@ * NOTES: OpenAT wip for 286-class machine with open BIOS. * PS2_M80-486 wip, pending receipt of TRM's for machine. * - * Version: @(#)machine_table.c 1.0.50 2019/11/19 + * Version: @(#)machine_table.c 1.0.55 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "machine.h" +#ifdef USE_NEW_DYNAREC +#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_S7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} +#define MACHINE_CPUS_PENTIUM_SS7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip_SS7}, {"AMD", cpus_K56_SS7}, {"Cyrix", cpus_6x86SS7}, {"", NULL}} +#else #if defined(DEV_BRANCH) && defined(USE_AMD_K) #define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} #if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86) @@ -52,6 +58,8 @@ #define MACHINE_CPUS_PENTIUM_S7 {{"Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"", NULL}, {"", NULL}, {"", NULL}} #endif #endif +#define MACHINE_CPUS_PENTIUM_SS7 MACHINE_CPUS_PENTIUM_S7 +#endif const machine_t machines[] = { { "[8088] AMI XT clone", "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, @@ -76,7 +84,7 @@ const machine_t machines[] = { { "[8088] Xi8088", "xi8088", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, { "[8088] Zenith Data SupersPort", "zdsupers", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 128, 640, 128, 0, machine_xt_zenith_init, NULL }, - { "[8086] Amstrad PC1512", "pc1512", {{"Intel", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, + { "[8086] Amstrad PC1512", "pc1512", {{"Intel", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, { "[8086] Amstrad PC1640", "pc1640", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc1640_init, pc1640_get_device }, { "[8086] Amstrad PC2086", "pc2086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc2086_init, pc2086_get_device }, { "[8086] Amstrad PC3086", "pc3086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc3086_init, pc3086_get_device }, @@ -91,6 +99,8 @@ const machine_t machines[] = { { "[286 ISA] AMI 286 clone", "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, { "[286 ISA] Award 286 clone", "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_award286_init, NULL }, + { "[286 ISA] Phoenix 286 clone", "px286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_px286_init, NULL }, + { "[286 ISA] Quadtel 286 clone", "quadt286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_quadt286_init, NULL }, { "[286 ISA] Commodore PC 30 III", "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, { "[286 ISA] Compaq Portable II", "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_portableii_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PORTABLE3) @@ -99,12 +109,15 @@ const machine_t machines[] = { { "[286 ISA] GW-286CT GEAR", "gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_gw286ct_init, NULL }, { "[286 ISA] Hyundai Super-286TR", "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_super286tr_init, NULL }, { "[286 ISA] IBM AT", "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL }, - { "[286 ISA] AMI IBM AT", "ibmatami", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatami_init, NULL }, - { "[286 ISA] Quadtel IBM AT", "ibmatquadtel", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, - { "[286 ISA] Phoenix IBM AT", "ibmatpx", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatpx_init, NULL }, + { "[286 ISA] AMI IBM AT", "ibmatami", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatami_init, NULL }, + { "[286 ISA] Quadtel IBM AT", "ibmatquadtel", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, + { "[286 ISA] Phoenix IBM AT", "ibmatpx", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatpx_init, NULL }, { "[286 ISA] IBM PS/1 model 2011", "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 512,16384, 512, 63, machine_ps1_m2011_init, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, + { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"Intel", cpus_ps2_m30_286}, {"IBM",cpus_IBM486SLC},{"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, { "[286 ISA] IBM XT Model 286", "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 127, machine_at_ibmxt286_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_SIEMENS) + { "[286 ISA] Siemens PCD-2L", "siemens", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_siemens_init, NULL }, +#endif #if defined(DEV_BRANCH) && defined(USE_OPEN_AT) { "[286 ISA] OpenAT", "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_open_at_init, NULL }, #endif @@ -113,30 +126,27 @@ const machine_t machines[] = { { "[286 ISA] Toshiba T3100e", "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, { "[286 ISA] Trigem 286M", "tg286m", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, - { "[286 ISA] Unknown Phoenix Headland", "headlandpho", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_headlandpho_init, NULL }, - { "[286 ISA] Unknown Quadtel Headland", "headlandquadtel", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_headlandquadtel_init, NULL }, - { "[286 ISA] Headland IQS", "iqs", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_iqs_init, NULL }, - { "[286 ISA] Samsung Deskmaster 286", "deskmaster286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_deskmaster286_init, NULL }, - - { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, + { "[286 ISA] Samsung Deskmaster 286", "deskmaster286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_deskmaster286_init, NULL }, + + { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"Intel", cpus_ps2_m30_286}, {"IBM",cpus_IBM486SLC},{"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, { "[386SX ISA] AMA-932J", "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, #if defined(DEV_BRANCH) && defined(USE_AMI386SX) { "[386SX ISA] AMI Unknown 386SX", "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL }, #endif { "[386SX ISA] Amstrad MegaPC", "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 32, 1, 127, machine_at_wd76c10_init, NULL }, + { "[386SX ISA] Commodore SL386SX", "cbm_sl386sx25", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1024, 8192, 512, 127, machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device }, { "[386SX ISA] DTK 386SX clone", "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_neat_init, NULL }, { "[386SX ISA] IBM PS/1 model 2121", "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, { "[386SX ISA] KMX-C-02", "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_kmxc02_init, NULL }, - { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM", cpus_IBM486SLC}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, + { "[386SX ISA] Goldstar 386", "goldstar386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_goldstar386_init, NULL }, + { "[386SX ISA] Micronics 09-00021", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_MICRONICS386) - { "[386SX ISA] Unknown Micronics 386 Board", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, -#endif + { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM",cpus_IBM486SLC},{"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, - { "[386DX ISA] AMI 386DX clone", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[386DX ISA] Dataexpert SX495 (386DX)", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, { "[386DX ISA] Award 386DX clone", "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_MR495) { "[386DX ISA] MR 386DX clone", "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -145,18 +155,18 @@ const machine_t machines[] = { { "[386DX ISA] Compaq Portable III (386)", "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 14, 1, 127, machine_at_portableiii386_init, NULL }, #endif - { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, - { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, + { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM",cpus_IBM486BL},{"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, + { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM",cpus_IBM486BL},{"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - { "[486 ISA] AMI 486 clone", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[486 ISA] AMI ALi 1429", "ali1429", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, + { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, + { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_PS1M2133) - { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, + { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, #endif #if defined(DEV_BRANCH) && defined(USE_MR495) { "[486 ISA] MR 486 clone", "mr486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, @@ -169,19 +179,25 @@ const machine_t machines[] = { #endif { "[486 PCI] Intel Classic/PCI", "alfredo", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL }, + { "[486 PCI] Lucky Star LS-486E", "ls486e", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_ls486e_init, NULL }, { "[486 PCI] Rise Computer R418", "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL }, + { "[486 PCI] Zida 4DPS", "4dps", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_4dps_init, NULL }, + { "[486 PCI] ASUS P/I-486SP3G", "486sp3g", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_486sp3g_init, NULL }, { "[Socket 4 LX] Intel Premiere/PCI", "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL }, - { "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL }, + { "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL }, +#if defined(DEV_BRANCH) && defined(USE_VPP60) + { "[Socket 4 LX] IBM PS/ValuePoint P60", "valuepointp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_valuepointp60_init, NULL }, +#endif { "[Socket 4 LX] Micro Star 586MC1", "586mc1", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_586mc1_init, NULL }, { "[Socket 5 NX] Intel Premiere/PCI II", "plato", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL }, - { "[Socket 5 NX] IBM Ambra DP90 PCI", "ambradp90", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp90_init, NULL }, + { "[Socket 5 NX] IBM Ambra DP90 PCI", "ambradp90", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp90_init, NULL }, { "[Socket 5 NX] Gigabyte GA-586IP", "430nx", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_430nx_init, NULL }, { "[Socket 5 FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_VECTRA54) - { "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_vectra54_init, NULL }, + { "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 255, machine_at_vectra54_init, NULL }, #endif { "[Socket 5 FX] Intel Advanced/ZP", "zappa", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, { "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, @@ -200,7 +216,8 @@ const machine_t machines[] = { { "[Socket 7 HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL }, { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, #if defined(DEV_BRANCH) && defined(USE_TC430HX) - { "[Socket 7 HX] TC430HX", "tc430hx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_tc430hx_init, NULL }, + { "[Socket 7 HX] TC430HX", "tc430hx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 255, machine_at_tc430hx_init, NULL }, + { "[Socket 7 HX] Toshiba Equium 5200D", "equium5200", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_equium5200_init, NULL }, #endif { "[Socket 7 VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, @@ -208,9 +225,25 @@ const machine_t machines[] = { { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, + { "[Socket 7 TX] Acorp 5TX52", "5tx52", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_5tx52_init, NULL }, + { "[Socket 7 TX] ASUS TXP4", "txp4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_txp4_init, NULL }, + { "[Socket 7 TX] Intel YM430TX", "ym430tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_ym430tx_init, NULL }, + { "[Socket 7 TX] San-LI/Superpower SP-586TX","sp586tx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_sp586tx_init, NULL }, + + { "[Super Socket 7] FIC VA-503+", "ficva503p", MACHINE_CPUS_PENTIUM_SS7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_mvp3_init, NULL }, + #if defined(DEV_BRANCH) && defined(USE_I686) { "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, { "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, + + { "[Slot 1 BX] Lucky Star 6ABX3", "6abx3", {{"Intel", cpus_PentiumII}, {"VIA", cpus_Cyrix3},{"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_6abx3_init, NULL }, +#else + { "[Slot 1 BX] Lucky Star 6ABX3", "6abx3", {{"VIA", cpus_Cyrix3}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_6abx3_init, NULL }, +#endif +#if defined(DEV_BRANCH) && defined(USE_I686) + { "[Slot 1 BX] ASUS P2B-LS", "p2bls", {{"Intel", cpus_PentiumII}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_p2bls_init, NULL }, + { "[Socket 370 BX] ECS P6BXT-A+", "p6bxt", {{"Intel", cpus_PGA370}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_p6bxt_init, NULL }, + { "[Socket 370 ZX] Soltek SL-63A1", "63a", {{"Intel", cpus_PGA370}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 255, machine_at_63a_init, NULL }, #endif { NULL, NULL, {{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}}, 0, 0, 0, 0, 0, NULL, NULL } }; diff --git a/src/machine/machine_table_new.c b/src/machine/machine_table_new.c deleted file mode 100644 index a46e7175c..000000000 --- a/src/machine/machine_table_new.c +++ /dev/null @@ -1,267 +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. - * - * Handling of the emulated machines. - * - * NOTES: OpenAT wip for 286-class machine with open BIOS. - * PS2_M80-486 wip, pending receipt of TRM's for machine. - * - * Version: @(#)machine_table.c 1.0.50 2019/11/19 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../cpu_new/cpu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "machine.h" - - -#define MACHINE_CPUS_PENTIUM_S5 {{ "Intel", cpus_PentiumS5}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"", NULL}, {"", NULL}} -#define MACHINE_CPUS_PENTIUM_S73V {{ "Intel", cpus_Pentium3V}, {"IDT", cpus_WinChip}, {"AMD", cpus_K5}, {"Cyrix", cpus_6x863V},{"", NULL}} -#define MACHINE_CPUS_PENTIUM_S7 {{ "Intel", cpus_Pentium}, {"IDT", cpus_WinChip}, {"AMD", cpus_K56}, {"Cyrix", cpus_6x86}, {"", NULL}} - -const machine_t machines[] = { - { "[8088] AMI XT clone", "amixt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_amixt_init, NULL }, - { "[8088] Compaq Portable", "portable", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO, 128, 640, 128, 0, machine_xt_compaq_init, NULL }, - { "[8088] DTK XT clone", "dtk", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_dtk_init, NULL }, - { "[8088] IBM PC (1981)", "ibmpc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 16, 64, 16, 0, machine_pc_init, NULL }, - { "[8088] IBM PC (1982)", "ibmpc82", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 256, 256, 256, 0, machine_pc82_init, NULL }, - { "[8088] IBM PCjr", "ibmpcjr", {{"Intel", cpus_pcjr}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_pcjr_init, pcjr_get_device }, - { "[8088] IBM XT (1982)", "ibmxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 256, 64, 0, machine_xt_init, NULL }, - { "[8088] IBM XT (1986)", "ibmxt86", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 256, 640, 64, 0, machine_xt86_init, NULL }, - { "[8088] Generic XT clone", "genxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_genxt_init, NULL }, - { "[8088] Juko XT clone", "jukopc", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_jukopc_init, NULL }, - { "[8088] OpenXT", "open_xt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_open_xt_init, NULL }, - { "[8088] Phoenix XT clone", "pxxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 64, 640, 64, 0, machine_xt_pxxt_init, NULL }, - { "[8088] Schneider EuroPC", "europc", {{"Siemens", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_HDC | MACHINE_MOUSE, 512, 640, 128, 15, machine_europc_init, NULL }, - { "[8088] Tandy 1000", "tandy", {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 128, 640, 128, 0, machine_tandy_init, tandy1k_get_device }, - { "[8088] Tandy 1000 HX", "tandy1000hx", {{"Intel", cpus_europc}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 256, 640, 128, 0, machine_tandy1000hx_init, tandy1k_hx_get_device }, - { "[8088] Toshiba T1000", "t1000", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO, 512, 1280, 768, 63, machine_xt_t1000_init, t1000_get_device }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8088] VTech Laser Turbo XT", "ltxt", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 256, 640, 256, 0, machine_xt_laserxt_init, NULL }, -#endif - { "[8088] Xi8088", "xi8088", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 64, 1024, 128, 127, machine_xt_xi8088_init, xi8088_get_device }, - { "[8088] Zenith Data SupersPort", "zdsupers", {{"Intel", cpus_8088}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 128, 640, 128, 0, machine_xt_zenith_init, NULL }, - - { "[8086] Amstrad PC1512", "pc1512", {{"Intel", cpus_pc1512}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 512, 640, 128, 63, machine_pc1512_init, pc1512_get_device }, - { "[8086] Amstrad PC1640", "pc1640", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc1640_init, pc1640_get_device }, - { "[8086] Amstrad PC2086", "pc2086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc2086_init, pc2086_get_device }, - { "[8086] Amstrad PC3086", "pc3086", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 640, 640, 0, 63, machine_pc3086_init, pc3086_get_device }, - { "[8086] Amstrad PC20(0)", "pc200", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_pc200_init, pc200_get_device }, - { "[8086] Amstrad PPC512/640", "ppc512", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_MOUSE | MACHINE_NONMI, 512, 640, 128, 63, machine_ppc512_init, ppc512_get_device }, - { "[8086] Olivetti M24", "olivetti_m24", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_MOUSE, 128, 640, 128, 0, machine_olim24_init, NULL }, - { "[8086] Tandy 1000 SL/2", "tandy1000sl2", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 512, 768, 128, 0, machine_tandy1000sl2_init, NULL }, - { "[8086] Toshiba T1200", "t1200", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VIDEO, 1024, 2048,1024, 63, machine_xt_t1200_init, t1200_get_device }, -#if defined(DEV_BRANCH) && defined(USE_LASERXT) - { "[8086] VTech Laser XT3", "lxt3", {{"Intel", cpus_8086}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA, 256, 640, 256, 0, machine_xt_lxt3_init, NULL }, -#endif - - { "[286 ISA] AMI 286 clone", "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL }, - { "[286 ISA] Award 286 clone", "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_award286_init, NULL }, - { "[286 ISA] Commodore PC 30 III", "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL }, - { "[286 ISA] Compaq Portable II", "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_portableii_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[286 ISA] Compaq Portable III", "portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 640,16384, 128, 127, machine_at_portableiii_init, NULL }, -#endif - { "[286 ISA] GW-286CT GEAR", "gw286ct", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_gw286ct_init, NULL }, - { "[286 ISA] Hyundai Super-286TR", "super286tr", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_super286tr_init, NULL }, - { "[286 ISA] IBM AT", "ibmat", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibm_init, NULL }, - { "[286 ISA] AMI IBM AT", "ibmatami", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatami_init, NULL }, - { "[286 ISA] Quadtel IBM AT", "ibmatquadtel", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatquadtel_init, NULL }, - { "[286 ISA] Phoenix IBM AT", "ibmatpx", {{"", cpus_ibmat}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_ibmatpx_init, NULL }, - { "[286 ISA] IBM PS/1 model 2011", "ibmps1es", {{"", cpus_ps1_m2011}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 512,16384, 512, 63, machine_ps1_m2011_init, NULL }, - { "[286 ISA] IBM PS/2 model 30-286", "ibmps2_m30_286", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC | MACHINE_PS2, 1, 16, 1, 127, machine_ps2_m30_286_init, NULL }, - { "[286 ISA] IBM XT Model 286", "ibmxt286", {{"", cpus_ibmxt286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 127, machine_at_ibmxt286_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_OPEN_AT) - { "[286 ISA] OpenAT", "open_at", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 256,15872, 128, 63, machine_at_open_at_init, NULL }, -#endif - { "[286 ISA] Samsung SPC-4200P", "spc4200p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 512, 2048, 128, 127, machine_at_spc4200p_init, NULL }, - { "[286 ISA] Samsung SPC-4216P", "spc4216p", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2, 1, 5, 1, 127, machine_at_spc4216p_init, NULL }, - { "[286 ISA] Toshiba T3100e", "t3100e", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO | MACHINE_VIDEO_FIXED | MACHINE_HDC, 1024, 5120, 256, 63, machine_at_t3100e_init, NULL }, - { "[286 ISA] Trigem 286M", "tg286m", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_tg286m_init, NULL }, - - { "[286 ISA] Unknown Phoenix Headland", "headlandpho", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_headlandpho_init, NULL }, - { "[286 ISA] Unknown Quadtel Headland", "headlandquadtel", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_headlandquadtel_init, NULL }, - { "[286 ISA] Headland IQS", "iqs", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_iqs_init, NULL }, - { "[286 ISA] Samsung Deskmaster 286", "deskmaster286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_deskmaster286_init, NULL }, - - { "[286 MCA] IBM PS/2 model 50", "ibmps2_m50", {{"Intel", cpus_ps2_m30_286}, {"IBM", cpus_IBM486SLC}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 10, 1, 63, machine_ps2_model_50_init, NULL }, - - { "[386SX ISA] AMA-932J", "ama932j", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 512, 8192, 128, 127, machine_at_ama932j_init, at_ama932j_get_device }, -#if defined(DEV_BRANCH) && defined(USE_AMI386SX) - { "[386SX ISA] AMI Unknown 386SX", "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL }, -#endif - { "[386SX ISA] Amstrad MegaPC", "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 32, 1, 127, machine_at_wd76c10_init, NULL }, - { "[386SX ISA] DTK 386SX clone", "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_neat_init, NULL }, - { "[386SX ISA] IBM PS/1 model 2121", "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, - { "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL }, - { "[386SX ISA] KMX-C-02", "kmxc02", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 512, 127, machine_at_kmxc02_init, NULL }, - -#if defined(DEV_BRANCH) && defined(USE_MICRONICS386) - { "[386SX ISA] Unknown Micronics 386 Board", "micronics386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL }, -#endif - - { "[386SX MCA] IBM PS/2 model 55SX", "ibmps2_m55sx", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"IBM", cpus_IBM486SLC}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 8, 1, 63, machine_ps2_model_55sx_init, NULL }, - - { "[386DX ISA] Dataexpert SX495 (386DX)", "ami386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[386DX ISA] Award 386DX clone", "award386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_MR495) - { "[386DX ISA] MR 386DX clone", "mr386dx", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, -#endif -#if defined(DEV_BRANCH) && defined(USE_PORTABLE3) - { "[386DX ISA] Compaq Portable III (386)", "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 14, 1, 127, machine_at_portableiii386_init, NULL }, -#endif - - { "[386DX MCA] IBM PS/2 model 70 (type 3)", "ibmps2_m70_type3", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type3_init, NULL }, - { "[386DX MCA] IBM PS/2 model 80", "ibmps2_m80", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"IBM", cpus_IBM486BL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 1, 12, 1, 63, machine_ps2_model_80_init, NULL }, - - { "[486 ISA] Dataexpert SX495 (486)", "ami486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_ami_init, NULL }, - { "[486 ISA] Olystar LIL1429", "ali1429", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_ali1429_init, NULL }, - { "[486 ISA] AMI SiS 471", "ami471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_ami471_init, NULL }, - { "[486 ISA] AMI WinBIOS 486", "win486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_winbios1429_init, NULL }, - { "[486 ISA] AMI WinBIOS SiS 471", "win471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_win471_init, NULL }, - { "[486 ISA] Award 486 clone", "award486", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_init, NULL }, - { "[486 ISA] DTK PKM-0038S E-2", "dtk486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_dtk486_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_PS1M2133) - { "[486 ISA] IBM PS/1 model 2133", "ibmps1_2133", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_NONMI, 1, 64, 1, 127, machine_ps1_m2133_init, NULL }, -#endif -#if defined(DEV_BRANCH) && defined(USE_MR495) - { "[486 ISA] MR 486 clone", "mr486", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 32, 1, 127, machine_at_opti495_mr_init, NULL }, -#endif - { "[486 ISA] Packard Bell PB410A", "pb410a", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 64, 1, 127, machine_at_pb410a_init, NULL }, - { "[486 ISA] Phoenix SiS 471", "px471", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 128, 1, 127, machine_at_px471_init, NULL }, - -#if defined(DEV_BRANCH) && defined(USE_PS2M70T4) - { "[486 MCA] IBM PS/2 model 70 (type 4)", "ibmps2_m70_type4", {{"Intel", cpus_i486S1}, {"AMD", cpus_Am486S1}, {"Cyrix", cpus_Cx486S1},{"", NULL}, {"", NULL}}, MACHINE_MCA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO, 2, 16, 2, 63, machine_ps2_model_70_type4_init, NULL }, -#endif - - { "[486 PCI] Intel Classic/PCI", "alfredo", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_alfredo_init, NULL }, - { "[486 PCI] Rise Computer R418", "r418", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_r418_init, NULL }, - - { "[Socket 4 LX] Intel Premiere/PCI", "revenge", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_batman_init, NULL }, - { "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL }, - { "[Socket 4 LX] Micro Star 586MC1", "586mc1", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_586mc1_init, NULL }, - - { "[Socket 5 NX] Intel Premiere/PCI II", "plato", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_plato_init, NULL }, - { "[Socket 5 NX] IBM Ambra DP90 PCI", "ambradp90", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp90_init, NULL }, - { "[Socket 5 NX] Gigabyte GA-586IP", "430nx", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_430nx_init, NULL }, - - { "[Socket 5 FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_VECTRA54) - { "[Socket 5 FX] HP Vectra VL 5 Series 4", "vectra54", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_vectra54_init, NULL }, -#endif - { "[Socket 5 FX] Intel Advanced/ZP", "zappa", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_zappa_init, NULL }, - { "[Socket 5 FX] PC Partner MB500N", "mb500n", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_mb500n_init, NULL }, - { "[Socket 5 FX] President Award 430FX PCI","president", MACHINE_CPUS_PENTIUM_S5, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_president_init, NULL }, - - { "[Socket 7 FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_MRTHOR) - { "[Socket 7 FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL }, -#endif - { "[Socket 7 FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device }, - { "[Socket 7 FX] Packard Bell PB640", "pb640", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_pb640_init, at_pb640_get_device }, - - { "[Socket 7 HX] Acer M3a", "acerm3a", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerm3a_init, NULL }, - { "[Socket 7 HX] Acer V35n", "acerv35n", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_acerv35n_init, NULL }, - { "[Socket 7 HX] AOpen AP53", "ap53", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_ap53_init, NULL }, - { "[Socket 7 HX] ASUS P/I-P55T2P4", "p55t2p4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_p55t2p4_init, NULL }, - { "[Socket 7 HX] SuperMicro Super P55T2S", "p55t2s", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_p55t2s_init, NULL }, -#if defined(DEV_BRANCH) && defined(USE_TC430HX) - { "[Socket 7 HX] TC430HX", "tc430hx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_tc430hx_init, NULL }, -#endif - - { "[Socket 7 VX] ASUS P/I-P55TVP4", "p55tvp4", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55tvp4_init, NULL }, - { "[Socket 7 VX] Epox P55-VA", "p55va", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL }, - { "[Socket 7 VX] Jetway J656VXD", "j656vxd", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_j656vxd_init, NULL }, - { "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL }, - -#if defined(DEV_BRANCH) && defined(USE_I686) - { "[Socket 8 FX] Tyan Titan-Pro AT", "440fx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_i440fx_init, NULL }, - { "[Socket 8 FX] Tyan Titan-Pro ATX", "tpatx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_s1668_init, NULL }, -#endif - { NULL, NULL, {{"", 0}, {"", 0}, {"", 0}, {"", 0}, {"", 0}}, 0, 0, 0, 0, 0, NULL, NULL } -}; - - -int -machine_count(void) -{ - return((sizeof(machines) / sizeof(machine)) - 1); -} - - -char * -machine_getname(void) -{ - return((char *)machines[machine].name); -} - - -char * -machine_getname_ex(int m) -{ - return((char *)machines[m].name); -} - - -const device_t * -machine_getdevice(int m) -{ - if (machines[m].get_device) - return(machines[m].get_device()); - - return(NULL); -} - - -char * -machine_get_internal_name(void) -{ - return((char *)machines[machine].internal_name); -} - - -char * -machine_get_internal_name_ex(int m) -{ - return((char *)machines[m].internal_name); -} - - -int -machine_get_nvrmask(int m) -{ - return(machines[m].nvrmask); -} - - -int -machine_get_machine_from_internal_name(char *s) -{ - int c = 0; - - while (machines[c].init != NULL) { - if (!strcmp(machines[c].internal_name, (const char *)s)) - return(c); - c++; - } - - return(0); -} diff --git a/src/mca.c b/src/mca.c index 73e227b8e..b9ab31487 100644 --- a/src/mca.c +++ b/src/mca.c @@ -2,7 +2,7 @@ #include #include #include -#include "io.h" +#include "86box_io.h" #include "mca.h" diff --git a/src/mem.c b/src/mem.c index 0741e18d5..114bca468 100644 --- a/src/mem.c +++ b/src/mem.c @@ -12,15 +12,15 @@ * the DYNAMIC_TABLES=1 enables this. Will eventually go * away, either way... * - * Version: @(#)mem.c 1.0.22 2019/12/02 + * Version: @(#)mem.c 1.0.23 2020/01/25 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -30,23 +30,27 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "cpu/cpu.h" -#include "cpu/x86_ops.h" -#include "cpu/x86.h" -#include "machine/machine.h" -#include "machine/m_xt_xi8088.h" +#include "cpu.h" +#include "x86_ops.h" +#include "x86.h" +#include "machine.h" +#include "m_xt_xi8088.h" #include "config.h" -#include "io.h" +#include "86box_io.h" #include "mem.h" #include "rom.h" #ifdef USE_DYNAREC -# include "cpu/codegen.h" +# include "codegen_public.h" +#else +#ifdef USE_NEW_DYNAREC +# define PAGE_MASK_SHIFT 6 #else # define PAGE_MASK_INDEX_MASK 3 # define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_MASK 63 # define PAGE_MASK_SHIFT 4 #endif +# define PAGE_MASK_MASK 63 +#endif #define FIXME 0 @@ -105,12 +109,18 @@ int mem_a20_key = 0, int mmuflush = 0; int mmu_perm = 4; +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + +uint32_t purgable_page_list_head = 0; +int purgeable_page_count = 0; + /* FIXME: re-do this with a 'mem_ops' struct. */ static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -static int _mem_state[MEM_MAPPINGS_NO]; +static int _mem_state[MEM_MAPPINGS_NO], _mem_state_bak[MEM_MAPPINGS_NO]; #if FIXME #if (MEM_GRANULARITY_BITS >= 12) @@ -433,13 +443,17 @@ addwritelookup(uint32_t virt, uint32_t phys) writelookup2[writelookup[writelnext]] = -1; } +#ifdef USE_NEW_DYNAREC + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) +#else #ifdef USE_DYNAREC if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) #else if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) +#endif #endif page_lookup[virt >> 12] = &pages[phys >> 12]; - else + else writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; writelookupp[writelnext] = mmu_perm; @@ -512,16 +526,15 @@ writemembl(uint32_t addr, uint8_t val) mem_mapping_t *map; mem_logical_addr = addr; - if (page_lookup[addr>>12]) - { + if (page_lookup[addr>>12]) { page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; } if (cr0 >> 31) { addr = mmutranslate_write(addr); - if (addr == 0xffffffff) return; + if (addr == 0xffffffff) + return; } addr &= rammask; @@ -530,6 +543,297 @@ writemembl(uint32_t addr, uint8_t val) map->write_b(addr, val, map->p); } + +#ifdef USE_NEW_DYNAREC +uint16_t +readmemwl(uint32_t addr) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (mmutranslate_read(addr) == 0xffffffff) + return 0xffff; + if (mmutranslate_read(addr+1) == 0xffffffff) + return 0xffff; + } + return readmembl(addr)|(readmembl(addr+1)<<8); + } else if (readlookup2[addr >> 12] != -1) + return *(uint16_t *)(readlookup2[addr >> 12] + addr); + } + if (cr0>>31) { + addr = mmutranslate_read(addr); + if (addr == 0xffffffff) + return 0xffff; + } + + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + + return 0xffff; +} + + +void +writememwl(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFFE) { + if (cr0 >> 31) { + if (mmutranslate_write(addr) == 0xffffffff) + return; + if (mmutranslate_write(addr+1) == 0xffffffff) + return; + } + writemembl(addr,val); + writemembl(addr+1,val>>8); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr>>12]) { + page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) + return; + } + + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_w) + map->write_w(addr, val, map->p); + else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + } + } +} + + +uint32_t +readmemll(uint32_t addr) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr&0xFFF)>0xFFC) { + if (cr0>>31) { + if (mmutranslate_read(addr) == 0xffffffff) + return 0xffffffff; + if (mmutranslate_read(addr+3) == 0xffffffff) + return 0xffffffff; + } + return readmemwl(addr)|(readmemwl(addr+2)<<16); + } else if (readlookup2[addr >> 12] != -1) + return *(uint32_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0>>31) { + addr = mmutranslate_read(addr); + if (addr==0xFFFFFFFF) + return 0xFFFFFFFF; + } + + addr&=rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->read_l) + return map->read_l(addr, map->p); + + if (map->read_w) + return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); + + if (map->read_b) + return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | + (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); + } + + return 0xffffffff; +} + + +void +writememll(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFFC) { + if (cr0>>31) { + if (mmutranslate_write(addr) == 0xffffffff) + return; + if (mmutranslate_write(addr+3) == 0xffffffff) + return; + } + writememwl(addr,val); + writememwl(addr+2,val>>16); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + if (page_lookup[addr>>12]) { + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) + return; + } + + addr&=rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_l) + map->write_l(addr, val, map->p); + else if (map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + } else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + } + } +} + + +uint64_t +readmemql(uint32_t addr) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 7) { + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFF8) { + if (cr0>>31) { + if (mmutranslate_read(addr) == 0xffffffff) + return 0xffffffff; + if (mmutranslate_read(addr+7) == 0xffffffff) + return 0xffffffff; + } + return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); + } else if (readlookup2[addr >> 12] != -1) + return *(uint64_t *)(readlookup2[addr >> 12] + addr); + } + + if (cr0>>31) { + addr = mmutranslate_read(addr); + if (addr==0xFFFFFFFF) + return 0xFFFFFFFF; + } + + addr&=rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_l) + return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); + + return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); +} + + +void +writememql(uint32_t addr, uint64_t val) +{ + mem_mapping_t *map; + + mem_logical_addr = addr; + + if (addr & 7) { + sub_cycles(timing_misaligned); + if ((addr & 0xFFF) > 0xFF8) { + if (cr0>>31) { + if (mmutranslate_write(addr) == 0xffffffff) + return; + if (mmutranslate_write(addr+7) == 0xffffffff) + return; + } + writememll(addr, val); + writememll(addr+4, val >> 32); + return; + } else if (writelookup2[addr >> 12] != -1) { + *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; + return; + } + } + if (page_lookup[addr>>12]) { + page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); + page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); + return; + } + if (cr0>>31) { + addr = mmutranslate_write(addr); + if (addr==0xFFFFFFFF) + return; + } + + addr&=rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_l) { + map->write_l(addr, val, map->p); + map->write_l(addr + 4, val >> 32, map->p); + } else if (map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + map->write_w(addr + 4, val >> 32, map->p); + map->write_w(addr + 6, val >> 48, map->p); + } else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + map->write_b(addr + 4, val >> 32, map->p); + map->write_b(addr + 5, val >> 40, map->p); + map->write_b(addr + 6, val >> 48, map->p); + map->write_b(addr + 7, val >> 56, map->p); + } + } +} +#else uint8_t readmemb386l(uint32_t seg, uint32_t addr) { @@ -553,10 +857,12 @@ readmemwl(uint32_t seg, uint32_t addr) if (addr2 & 1) { if (!cpu_cyrix_alignment || (addr2 & 7) == 7) sub_cycles(timing_misaligned); - if ((addr2 & 0xFFF) > 0xffe) { + if ((addr2 & 0xfff) > 0xffe) { if (cr0 >> 31) { - if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff; - if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff; + if (mmutranslate_read(addr2) == 0xffffffff) + return 0xffff; + if (mmutranslate_read(addr2+1) == 0xffffffff) + return 0xffff; } if (is386) return readmemb386l(seg,addr)|(((uint16_t) readmemb386l(seg,addr+1))<<8); else return readmembl(seg+addr)|(((uint16_t) readmembl(seg+addr+1))<<8); @@ -568,7 +874,7 @@ readmemwl(uint32_t seg, uint32_t addr) if (cr0 >> 31) { addr2 = mmutranslate_read(addr2); if (addr2 == 0xffffffff) - return 0xFFFF; + return 0xffff; } addr2 &= rammask; @@ -843,6 +1149,7 @@ writememql(uint32_t seg, uint32_t addr, uint64_t val) return; } } +#endif int @@ -894,6 +1201,7 @@ mem_readw_phys(uint32_t addr) return temp; } + uint32_t mem_readl_phys(uint32_t addr) { @@ -914,6 +1222,7 @@ mem_readl_phys(uint32_t addr) return temp; } + void mem_writeb_phys(uint32_t addr, uint8_t val) { @@ -925,6 +1234,7 @@ mem_writeb_phys(uint32_t addr, uint8_t val) map->write_b(addr, val, map->p); } + void mem_writel_phys(uint32_t addr, uint32_t val) { @@ -943,6 +1253,7 @@ mem_writel_phys(uint32_t addr, uint32_t val) } } + uint8_t mem_read_ram(uint32_t addr, void *priv) { @@ -970,6 +1281,114 @@ mem_read_raml(uint32_t addr, void *priv) } +#ifdef USE_NEW_DYNAREC +static inline int +page_index(page_t *p) +{ + return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); +} + + +void +page_add_to_evict_list(page_t *p) +{ + pages[purgable_page_list_head].evict_prev = page_index(p); + p->evict_next = purgable_page_list_head; + p->evict_prev = 0; + purgable_page_list_head = pages[purgable_page_list_head].evict_prev; + purgeable_page_count++; +} + + +void +page_remove_from_evict_list(page_t *p) +{ + if (!page_in_evict_list(p)) + fatal("page_remove_from_evict_list: not in evict list!\n"); + if (p->evict_prev) + pages[p->evict_prev].evict_next = p->evict_next; + else + purgable_page_list_head = p->evict_next; + if (p->evict_next) + pages[p->evict_next].evict_prev = p->evict_prev; + p->evict_prev = EVICT_NOT_IN_LIST; + purgeable_page_count--; +} + + +void +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ + if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + + p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + + +void +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ + if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + *(uint16_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { + p->byte_dirty_mask[byte_offset+1] |= 1; + if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } else + byte_mask |= (byte_mask << 1); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + + +void +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ + if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { + uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + *(uint32_t *)&p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + p->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + + p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; + if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } + } +} +#else void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) { @@ -1017,6 +1436,7 @@ mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) *(uint32_t *)&p->mem[addr & 0xfff] = val; } } +#endif void @@ -1169,12 +1589,32 @@ mem_write_nulll(uint32_t addr, uint32_t val, void *p) void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) { + uint64_t mask; +#ifdef USE_NEW_DYNAREC + page_t *p; + + start_addr &= ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + + for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { + if ((start_addr >> 12) >= pages_sz) + continue; + + mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + + p = &pages[start_addr >> 12]; + + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +#else uint32_t cur_addr; start_addr &= ~PAGE_MASK_MASK; end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { - uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses may crash the emulator. */ @@ -1182,6 +1622,7 @@ mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) if (cur_addr < pages_sz) pages[cur_addr].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; } +#endif } @@ -1278,11 +1719,11 @@ mem_mapping_recalc(uint64_t base, uint64_t size) for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { if ((map->read_b || map->read_w || map->read_l) && mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) { + read_mapping[c >> MEM_GRANULARITY_BITS] = map; if (map->exec) _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); else _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - read_mapping[c >> MEM_GRANULARITY_BITS] = map; } if ((map->write_b || map->write_w || map->write_l) && mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) @@ -1440,8 +1881,22 @@ mem_set_mem_state(uint32_t base, uint32_t size, int state) { uint32_t c; - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + _mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state[(c + base) >> MEM_GRANULARITY_BITS]; _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = state; + } + + mem_mapping_recalc(base, size); +} + + +void +mem_restore_mem_state(uint32_t base, uint32_t size) +{ + uint32_t c; + + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) + _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = _mem_state_bak[(c + base) >> MEM_GRANULARITY_BITS]; mem_mapping_recalc(base, size); } @@ -1521,11 +1976,17 @@ mem_reset(void) m = 4096; } else { /* 80386+; maximum address space is 4GB. */ - m = (mem_size + 384) >> 2; - if ((m << 2) < (mem_size + 384)) - m++; - if (m < 4096) - m = 4096; + if (is486) { + /* We need this since there might be BIOS execution at the end of RAM, + which could break the recompiler if there's not enough page elements. */ + m = 1048576; + } else { + m = (mem_size + 384) >> 2; + if ((m << 2) < (mem_size + 384)) + m++; + if (m < 4096) + m = 4096; + } } } else { /* 8088/86; maximum address space is 1MB. */ @@ -1572,12 +2033,32 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); memset(pages, 0x00, pages_sz*sizeof(page_t)); +#ifdef USE_NEW_DYNAREC + if (byte_dirty_mask) { + free(byte_dirty_mask); + byte_dirty_mask = NULL; + } + byte_dirty_mask = malloc((mem_size * 1024) / 8); + memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); + + if (byte_code_present_mask) { + free(byte_code_present_mask); + byte_code_present_mask = NULL; + } + byte_code_present_mask = malloc((mem_size * 1024) / 8); + memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); +#endif for (c = 0; c < pages_sz; c++) { pages[c].mem = &ram[c << 12]; pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif } memset(_mem_exec, 0x00, sizeof(_mem_exec)); @@ -1585,6 +2066,7 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); memset(&base_mapping, 0x00, sizeof(base_mapping)); memset(_mem_state, 0x00, sizeof(_mem_state)); + memset(_mem_state_bak, 0x00, sizeof(_mem_state_bak)); mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); @@ -1630,6 +2112,11 @@ mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); mem_mapping_disable(&ram_remapped_mapping); mem_a20_init(); + +#ifdef USE_NEW_DYNAREC + purgable_page_list_head = 0; + purgeable_page_count = 0; +#endif } @@ -1667,7 +2154,7 @@ mem_remap_top(int kb) { int c; uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int size = mem_size - 640; + int offset, size = mem_size - 640; mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); if (mem_size <= 640) return; @@ -1683,10 +2170,16 @@ mem_remap_top(int kb) size = kb; for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { - pages[c].mem = &ram[0xA0000 + ((c - ((start * 1024) >> 12)) << 12)]; + offset = c - ((start * 1024) >> 12); + pages[c].mem = &ram[0xA0000 + (offset << 12)]; pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; +#endif } mem_set_mem_state(start * 1024, size * 1024, @@ -1697,6 +2190,7 @@ mem_remap_top(int kb) flushmmucache(); } + void mem_reset_page_blocks(void) { @@ -1708,8 +2202,13 @@ mem_reset_page_blocks(void) pages[c].write_b = mem_write_ramb_page; pages[c].write_w = mem_write_ramw_page; pages[c].write_l = mem_write_raml_page; +#ifdef USE_NEW_DYNAREC + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; +#else pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; +#endif } } diff --git a/src/mem.h b/src/mem.h index 6b5641ee6..badcb2d3c 100644 --- a/src/mem.h +++ b/src/mem.h @@ -8,15 +8,15 @@ * * Definitions for the memory interface. * - * Version: @(#)mem.h 1.0.10 2019/10/19 + * Version: @(#)mem.h 1.0.11 2020/01/25 * * Authors: Sarah Walker, * Fred N. van Kempen, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. */ #ifndef EMU_MEM_H # define EMU_MEM_H @@ -262,6 +262,7 @@ extern void mem_mapping_disable(mem_mapping_t *); extern void mem_mapping_enable(mem_mapping_t *); extern void mem_set_mem_state(uint32_t base, uint32_t size, int state); +extern void mem_restore_mem_state(uint32_t base, uint32_t size); extern uint8_t mem_readb_phys(uint32_t addr); extern uint16_t mem_readw_phys(uint32_t addr); @@ -302,6 +303,7 @@ extern void flushmmucache_cr3(void); extern void flushmmucache_nopc(void); extern void mmu_invalidate(uint32_t addr); +extern void mem_a20_init(void); extern void mem_a20_recalc(void); extern void mem_add_upper_bios(void); diff --git a/src/mem_new.c b/src/mem_new.c deleted file mode 100644 index 4fd4dbc91..000000000 --- a/src/mem_new.c +++ /dev/null @@ -1,1802 +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. - * - * Memory handling and MMU. - * - * NOTE: Experimenting with dynamically allocated lookup tables; - * the DYNAMIC_TABLES=1 enables this. Will eventually go - * away, either way... - * - * Version: @(#)mem.c 1.0.22 2019/12/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cpu_new/cpu.h" -#include "cpu_new/x86_ops.h" -#include "cpu_new/x86.h" -#include "machine/machine.h" -#include "machine/m_xt_xi8088.h" -#include "config.h" -#include "io.h" -#include "mem.h" -#include "rom.h" -#ifdef USE_DYNAREC -# include "cpu_new/codegen.h" -#else -# define PAGE_MASK_INDEX_MASK 3 -# define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_MASK 63 -# define PAGE_MASK_SHIFT 4 -#endif - - -#define FIXME 0 -#define DYNAMIC_TABLES 0 /* experimental */ - - -mem_mapping_t base_mapping, - ram_low_mapping, /* 0..640K mapping */ -#if 1 - ram_mid_mapping, -#endif - ram_remapped_mapping, /* 640..1024K mapping */ - ram_high_mapping, /* 1024K+ mapping */ - ram_remapped_mapping, - ram_split_mapping, - bios_mapping, - bios_high_mapping; - -page_t *pages, /* RAM page table */ - **page_lookup; /* pagetable lookup */ -uint32_t pages_sz; /* #pages in table */ - -uint8_t *ram; /* the virtual RAM */ -uint32_t rammask; - -uint8_t *rom; /* the virtual ROM */ -uint32_t biosmask, biosaddr; - -uint32_t pccache; -uint8_t *pccache2; - -int readlnext; -int readlookup[256], - readlookupp[256]; -uintptr_t *readlookup2; -int writelnext; -int writelookup[256], - writelookupp[256]; -uintptr_t *writelookup2; - -uint32_t mem_logical_addr; - -int shadowbios = 0, - shadowbios_write; -int readlnum = 0, - writelnum = 0; -int cachesize = 256; - -uint32_t get_phys_virt, - get_phys_phys; - -int mem_a20_key = 0, - mem_a20_alt = 0, - mem_a20_state = 0; - -int mmuflush = 0; -int mmu_perm = 4; - -uint64_t *byte_dirty_mask; -uint64_t *byte_code_present_mask; - -uint32_t purgable_page_list_head = 0; -int purgeable_page_count = 0; - - -/* FIXME: re-do this with a 'mem_ops' struct. */ -static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; -static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -static int _mem_state[MEM_MAPPINGS_NO]; - -#if FIXME -#if (MEM_GRANULARITY_BITS >= 12) -static uint8_t ff_array[MEM_GRANULARITY_SIZE]; -#else -static uint8_t ff_array[4096]; /* Must be at least one page. */ -#endif -#else -static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; -#endif - - -#ifdef ENABLE_MEM_LOG -int mem_do_log = ENABLE_MEM_LOG; - - -static void -mem_log(const char *fmt, ...) -{ - va_list ap; - - if (mem_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -#define mem_log(fmt, ...) -#endif - - -int -mem_addr_is_ram(uint32_t addr) -{ - mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping); -} - - -void -resetreadlookup(void) -{ - int c; - - /* This is NULL after app startup, when mem_init() has not yet run. */ -#if DYNAMIC_TABLES -mem_log("MEM: reset_lookup: pages=%08lx, lookup=%08lx, pages_sz=%i\n", pages, page_lookup, pages_sz); -#endif - - /* Initialize the page lookup table. */ -#if DYNAMIC_TABLES - memset(page_lookup, 0x00, pages_sz*sizeof(page_t *)); -#else - memset(page_lookup, 0x00, (1<<20)*sizeof(page_t *)); -#endif - - /* Initialize the tables for lower (<= 1024K) RAM. */ - for (c = 0; c < 256; c++) { - readlookup[c] = 0xffffffff; - writelookup[c] = 0xffffffff; - } - - /* Initialize the tables for high (> 1024K) RAM. */ -#if DYNAMIC_TABLES - memset(readlookup2, 0xff, pages_sz*sizeof(uintptr_t)); - memset(writelookup2, 0xff, pages_sz*sizeof(uintptr_t)); -#else - memset(readlookup2, 0xff, (1<<20)*sizeof(uintptr_t)); - memset(writelookup2, 0xff, (1<<20)*sizeof(uintptr_t)); -#endif - - readlnext = 0; - writelnext = 0; - pccache = 0xffffffff; -} - - -void -flushmmucache(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } - mmuflush++; - - pccache = (uint32_t)0xffffffff; - pccache2 = (uint8_t *)0xffffffff; - -#ifdef USE_DYNAREC - codegen_flush(); -#endif -} - - -void -flushmmucache_nopc(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } -} - - -void -flushmmucache_cr3(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = -1; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - writelookup2[writelookup[c]] = -1; - writelookup[c] = 0xffffffff; - } - } -} - - -void -mem_flush_write_page(uint32_t addr, uint32_t virt) -{ - page_t *page_target = &pages[addr >> 12]; - int c; - - for (c = 0; c < 256; c++) { - if (writelookup[c] != (int) 0xffffffff) { - uintptr_t target = (uintptr_t)&ram[(uintptr_t)(addr & ~0xfff) - (virt & ~0xfff)]; - - if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { - writelookup2[writelookup[c]] = -1; - page_lookup[writelookup[c]] = NULL; - writelookup[c] = 0xffffffff; - } - } - } -} - - -#define mmutranslate_read(addr) mmutranslatereal(addr,0) -#define mmutranslate_write(addr) mmutranslatereal(addr,1) -#define rammap(x) ((uint32_t *)(_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] - -uint32_t -mmutranslatereal(uint32_t addr, int rw) -{ - uint32_t temp,temp2,temp3; - uint32_t addr2; - - if (cpu_state.abrt) return -1; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - if (! (temp&1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return -1; - } - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3 && !cpl_override) || cr0 & WP_FLAG))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - - return -1; - } - - mmu_perm = temp & 4; - rammap(addr2) |= 0x20; - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && ((CPL == 3 && !cpl_override) || cr0&WP_FLAG))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) temp |= 4; - if (rw) temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return -1; - } - - mmu_perm = temp & 4; - rammap(addr2) |= 0x20; - rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw?0x60:0x20); - - return (temp&~0xfff)+(addr&0xfff); -} - - -uint32_t -mmutranslate_noabrt(uint32_t addr, int rw) -{ - uint32_t temp,temp2,temp3; - uint32_t addr2; - - if (cpu_state.abrt) - return -1; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - - if (! (temp & 1)) - return -1; - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if ((CPL == 3 && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (CPL == 3 || cr0 & WP_FLAG))) - return -1; - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - - if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG))) - return -1; - - return (temp & ~0xfff) + (addr & 0xfff); -} - - -void -mmu_invalidate(uint32_t addr) -{ - flushmmucache_cr3(); -} - - -uint8_t -mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) -{ - if (addr < start) - return 0; - else if (addr >= (start + len)) - return 0; - else - return 1; -} - - -uint32_t -mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) -{ - uint32_t mask = len - 1; - - return chunk_start + (addr & mask); -} - - -void -addreadlookup(uint32_t virt, uint32_t phys) -{ - if (virt == 0xffffffff) return; - - if (readlookup2[virt>>12] != (uintptr_t) -1) return; - - if (readlookup[readlnext] != (int) 0xffffffff) - readlookup2[readlookup[readlnext]] = -1; - - readlookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; - - readlookupp[readlnext] = mmu_perm; - readlookup[readlnext++] = virt >> 12; - readlnext &= (cachesize-1); - - sub_cycles(9); -} - - -void -addwritelookup(uint32_t virt, uint32_t phys) -{ - if (virt == 0xffffffff) return; - - if (page_lookup[virt >> 12]) return; - - if (writelookup[writelnext] != -1) { - page_lookup[writelookup[writelnext]] = NULL; - writelookup2[writelookup[writelnext]] = -1; - } - - if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) - page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; - else - writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)]; - - writelookupp[writelnext] = mmu_perm; - writelookup[writelnext++] = virt >> 12; - writelnext &= (cachesize - 1); - - sub_cycles(9); -} - - -uint8_t * -getpccache(uint32_t a) -{ - uint32_t a2; - - a2 = a; - - if (cr0 >> 31) { - a = mmutranslate_read(a); - - if (a == 0xffffffff) return ram; - } - a &= rammask; - - if (_mem_exec[a >> MEM_GRANULARITY_BITS]) { - if (is286) { - if (read_mapping[a >> MEM_GRANULARITY_BITS] && (read_mapping[a >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM)) - cpu_prefetch_cycles = cpu_rom_prefetch_cycles; - else - cpu_prefetch_cycles = cpu_mem_prefetch_cycles; - } - - return &_mem_exec[a >> MEM_GRANULARITY_BITS][(uintptr_t)(a & MEM_GRANULARITY_PAGE) - (uintptr_t)(a2 & ~0xfff)]; - } - - mem_log("Bad getpccache %08X\n", a); - -#if FIXME - return &ff_array[0-(uintptr_t)(a2 & ~0xfff)]; -#else - return (uint8_t *)&ff_pccache; -#endif -} - - -uint8_t -readmembl(uint32_t addr) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - if (cr0 >> 31) { - addr = mmutranslate_read(addr); - if (addr == 0xFFFFFFFF) return 0xFF; - } - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_b) - return map->read_b(addr, map->p); - return 0xFF; -} - - -void -writemembl(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (page_lookup[addr>>12]) { - page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0 >> 31) { - addr = mmutranslate_write(addr); - if (addr == 0xFFFFFFFF) - return; - } - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->write_b) - return map->write_b(addr, val, map->p); -} - - -uint16_t -readmemwl(uint32_t addr) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFFE) { - if (cr0 >> 31) { - if (mmutranslate_read(addr) == 0xffffffff) - return 0xffff; - if (mmutranslate_read(addr+1) == 0xffffffff) - return 0xffff; - } - return readmembl(addr)|(readmembl(addr+1)<<8); - } else if (readlookup2[addr >> 12] != -1) - return *(uint16_t *)(readlookup2[addr >> 12] + addr); - } - if (cr0>>31) { - addr = mmutranslate_read(addr); - if (addr==0xFFFFFFFF) - return 0xFFFF; - } - - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->read_w) - return map->read_w(addr, map->p); - - if (map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); - } - - return 0xffff; -} - - -void -writememwl(uint32_t addr, uint16_t val) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFFE) { - if (cr0 >> 31) { - if (mmutranslate_write(addr) == 0xffffffff) - return; - if (mmutranslate_write(addr+1) == 0xffffffff) - return; - } - writemembl(addr,val); - writemembl(addr+1,val>>8); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint16_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr>>12]) { - page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr = mmutranslate_write(addr); - if (addr==0xFFFFFFFF) - return; - } - - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_w) - map->write_w(addr, val, map->p); - else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - } - } -} - - -uint32_t -readmemll(uint32_t addr) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr&0xFFF)>0xFFC) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffff) - return 0xffffffff; - if (mmutranslate_read(addr+3) == 0xffffffff) - return 0xffffffff; - } - return readmemwl(addr)|(readmemwl(addr+2)<<16); - } else if (readlookup2[addr >> 12] != -1) - return *(uint32_t *)(readlookup2[addr >> 12] + addr); - } - - if (cr0>>31) { - addr = mmutranslate_read(addr); - if (addr==0xFFFFFFFF) - return 0xFFFFFFFF; - } - - addr&=rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->read_l) - return map->read_l(addr, map->p); - - if (map->read_w) - return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16); - - if (map->read_b) - return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) | - (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24); - } - - return 0xffffffff; -} - - -void -writememll(uint32_t addr, uint32_t val) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFFC) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffff) - return; - if (mmutranslate_write(addr+3) == 0xffffffff) - return; - } - writememwl(addr,val); - writememwl(addr+2,val>>16); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint32_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - if (page_lookup[addr>>12]) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr = mmutranslate_write(addr); - if (addr==0xFFFFFFFF) - return; - } - - addr&=rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) - map->write_l(addr, val, map->p); - else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - } - } -} - - -uint64_t -readmemql(uint32_t addr) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 7) { - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_read(addr) == 0xffffffff) - return 0xffffffff; - if (mmutranslate_read(addr+7) == 0xffffffff) - return 0xffffffff; - } - return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32); - } else if (readlookup2[addr >> 12] != -1) - return *(uint64_t *)(readlookup2[addr >> 12] + addr); - } - - if (cr0>>31) { - addr = mmutranslate_read(addr); - if (addr==0xFFFFFFFF) - return 0xFFFFFFFF; - } - - addr&=rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32); - - return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32); -} - - -void -writememql(uint32_t addr, uint64_t val) -{ - mem_mapping_t *map; - - mem_logical_addr = addr; - - if (addr & 7) { - sub_cycles(timing_misaligned); - if ((addr & 0xFFF) > 0xFF8) { - if (cr0>>31) { - if (mmutranslate_write(addr) == 0xffffffff) - return; - if (mmutranslate_write(addr+7) == 0xffffffff) - return; - } - writememll(addr, val); - writememll(addr+4, val >> 32); - return; - } else if (writelookup2[addr >> 12] != -1) { - *(uint64_t *)(writelookup2[addr >> 12] + addr) = val; - return; - } - } - if (page_lookup[addr>>12]) { - page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]); - page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]); - return; - } - if (cr0>>31) { - addr = mmutranslate_write(addr); - if (addr==0xFFFFFFFF) - return; - } - - addr&=rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_l) { - map->write_l(addr, val, map->p); - map->write_l(addr + 4, val >> 32, map->p); - } else if (map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - map->write_w(addr + 4, val >> 32, map->p); - map->write_w(addr + 6, val >> 48, map->p); - } else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - map->write_b(addr + 4, val >> 32, map->p); - map->write_b(addr + 5, val >> 40, map->p); - map->write_b(addr + 6, val >> 48, map->p); - map->write_b(addr + 7, val >> 56, map->p); - } - } -} - - -int -mem_mapping_is_romcs(uint32_t addr, int write) -{ - mem_mapping_t *map; - - if (write) - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - else - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map) - return !!(map->flags & MEM_MAPPING_ROMCS); - else - return 0; -} - - -uint8_t -mem_readb_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - return _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK]; - else if (map && map->read_b) - return map->read_b(addr, map->p); - else - return 0xff; -} - - -uint16_t -mem_readw_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - uint16_t temp; - - if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - return ((uint16_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK]; - else if (map && map->read_w) - return map->read_w(addr, map->p); - else { - temp = mem_readb_phys(addr + 1) << 8; - temp |= mem_readb_phys(addr); - } - - return temp; -} - -uint32_t -mem_readl_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - uint32_t temp; - - if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - return ((uint32_t *) _mem_exec[addr >> MEM_GRANULARITY_BITS])[(addr >> 1) & MEM_GRANULARITY_HMASK]; - else if (map && map->read_l) - return map->read_l(addr, map->p); - else { - temp = mem_readb_phys(addr + 3) << 24; - temp |= mem_readb_phys(addr + 2) << 16; - temp |= mem_readb_phys(addr + 1) << 8; - temp |= mem_readb_phys(addr); - } - - return temp; -} - - -void -mem_writeb_phys(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; - else if (map && map->write_b) - map->write_b(addr, val, map->p); -} - -void -mem_writel_phys(uint32_t addr, uint32_t val) -{ - mem_mapping_t *map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (_mem_exec[addr >> MEM_GRANULARITY_BITS]) - _mem_exec[addr >> MEM_GRANULARITY_BITS][addr & MEM_GRANULARITY_MASK] = val; - else if (map && map->write_l) - map->write_l(addr, val, map->p); - else - { - mem_writeb_phys(addr, val & 0xff); - mem_writeb_phys(addr + 1, (val >> 8) & 0xff); - mem_writeb_phys(addr + 2, (val >> 16) & 0xff); - mem_writeb_phys(addr + 3, (val >> 24) & 0xff); - } -} - -uint8_t -mem_read_ram(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - - return ram[addr]; -} - - -uint16_t -mem_read_ramw(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - - return *(uint16_t *)&ram[addr]; -} - - -uint32_t -mem_read_raml(uint32_t addr, void *priv) -{ - addreadlookup(mem_logical_addr, addr); - - return *(uint32_t *)&ram[addr]; -} - - -static inline int -page_index(page_t *p) -{ - return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t); -} - - -void -page_add_to_evict_list(page_t *p) -{ - pages[purgable_page_list_head].evict_prev = page_index(p); - p->evict_next = purgable_page_list_head; - p->evict_prev = 0; - purgable_page_list_head = pages[purgable_page_list_head].evict_prev; - purgeable_page_count++; -} - - -void -page_remove_from_evict_list(page_t *p) -{ - if (!page_in_evict_list(p)) - fatal("page_remove_from_evict_list: not in evict list!\n"); - if (p->evict_prev) - pages[p->evict_prev].evict_next = p->evict_next; - else - purgable_page_list_head = p->evict_next; - if (p->evict_next) - pages[p->evict_next].evict_prev = p->evict_prev; - p->evict_prev = EVICT_NOT_IN_LIST; - purgeable_page_count--; -} - - -void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) -{ - if (val != p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); - - p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - p->byte_dirty_mask[byte_offset] |= byte_mask; - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - - -void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) -{ - if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - *(uint16_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { - p->byte_dirty_mask[byte_offset+1] |= 1; - if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } else - byte_mask |= (byte_mask << 1); - - p->byte_dirty_mask[byte_offset] |= byte_mask; - - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - - -void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) -{ - if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile) { - uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - *(uint32_t *)&p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - p->byte_dirty_mask[byte_offset] |= byte_mask; - if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3)) { - uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); - - p->byte_dirty_mask[byte_offset+1] |= byte_mask_2; - if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } - } -} - - -void -mem_write_ram(uint32_t addr, uint8_t val, void *priv) -{ - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[addr >> 12]); -} - - -void -mem_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[addr >> 12]); -} - - -void -mem_write_raml(uint32_t addr, uint32_t val, void *priv) -{ - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[addr >> 12]); -} - - -static uint8_t -mem_read_remapped(uint32_t addr, void *priv) -{ - if(addr >= (mem_size * 1024) && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return ram[addr]; -} - - -static uint16_t -mem_read_remappedw(uint32_t addr, void *priv) -{ - if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *)&ram[addr]; -} - - -static uint32_t -mem_read_remappedl(uint32_t addr, void *priv) -{ - if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *)&ram[addr]; -} - - -static void -mem_write_remapped(uint32_t addr, uint8_t val, void *priv) -{ - uint32_t oldaddr = addr; - if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); -} - - -static void -mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) -{ - uint32_t oldaddr = addr; - if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); -} - - -static void -mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) -{ - uint32_t oldaddr = addr; - if(addr >= mem_size * 1024 && addr < ((mem_size + 384) * 1024)) - addr = 0xA0000 + (addr - (mem_size * 1024)); - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); -} - - -uint8_t -mem_read_bios(uint32_t addr, void *priv) -{ - uint8_t ret = 0xff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = rom[addr - biosaddr]; - - return ret; -} - - -uint16_t -mem_read_biosw(uint32_t addr, void *priv) -{ - uint16_t ret = 0xffff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint16_t *)&rom[addr - biosaddr]; - - return ret; -} - - -uint32_t -mem_read_biosl(uint32_t addr, void *priv) -{ - uint32_t ret = 0xffffffff; - - addr &= 0x000fffff; - - if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) - ret = *(uint32_t *)&rom[addr - biosaddr]; - - return ret; -} - - -void -mem_write_null(uint32_t addr, uint8_t val, void *p) -{ -} - - -void -mem_write_nullw(uint32_t addr, uint16_t val, void *p) -{ -} - - -void -mem_write_nulll(uint32_t addr, uint32_t val, void *p) -{ -} - - -void -mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) -{ - uint64_t mask; - page_t *p; - - start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - - for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT)) { - if ((start_addr >> 12) >= pages_sz) - continue; - - mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - - p = &pages[start_addr >> 12]; - - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - - -static __inline int -mem_mapping_read_allowed(uint32_t flags, int state) -{ - switch (state & MEM_READ_MASK) { - case MEM_READ_DISABLED: - return 0; - - case MEM_READ_ANY: - return 1; - - /* On external and 0 mappings without ROMCS. */ - case MEM_READ_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS); - - /* On external and 0 mappings with ROMCS. */ - case MEM_READ_ROMCS: - return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS); - - /* On any external mappings. */ - case MEM_READ_EXTANY: - return !(flags & MEM_MAPPING_INTERNAL); - - case MEM_READ_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL); - - default: - fatal("mem_mapping_read_allowed : bad state %x\n", state); - } - - return 0; -} - - -static __inline int -mem_mapping_write_allowed(uint32_t flags, int state) -{ - switch (state & MEM_WRITE_MASK) { - case MEM_WRITE_DISABLED: - return 0; - - case MEM_WRITE_ANY: - return 1; - - /* On external and 0 mappings without ROMCS. */ - case MEM_WRITE_EXTERNAL: - return !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_ROMCS); - - /* On external and 0 mappings with ROMCS. */ - case MEM_WRITE_ROMCS: - return !(flags & MEM_MAPPING_INTERNAL) && (flags & MEM_MAPPING_ROMCS); - - /* On any external mappings. */ - case MEM_WRITE_EXTANY: - return !(flags & MEM_MAPPING_INTERNAL); - - case MEM_WRITE_INTERNAL: - return !(flags & MEM_MAPPING_EXTERNAL); - - default: - fatal("mem_mapping_write_allowed : bad state %x\n", state); - } - - return 0; -} - - -static void -mem_mapping_recalc(uint64_t base, uint64_t size) -{ - mem_mapping_t *map = base_mapping.next; - uint64_t c; - - if (! size) return; - - /* Clear out old mappings. */ - for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { - read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - } - - /* Walk mapping list. */ - while (map != NULL) { - /*In range?*/ - if (map->enable && (uint64_t)map->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)map->base + (uint64_t)map->size) > (uint64_t)base) { - uint64_t start = (map->base < base) ? map->base : base; - uint64_t end = (((uint64_t)map->base + (uint64_t)map->size) < (base + size)) ? ((uint64_t)map->base + (uint64_t)map->size) : (base + size); - if (start < map->base) - start = map->base; - - for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { - if ((map->read_b || map->read_w || map->read_l) && - mem_mapping_read_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) { - read_mapping[c >> MEM_GRANULARITY_BITS] = map; - if (map->exec) - _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); - else - _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - } - if ((map->write_b || map->write_w || map->write_l) && - mem_mapping_write_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS])) - write_mapping[c >> MEM_GRANULARITY_BITS] = map; - } - } - map = map->next; - } - - flushmmucache_cr3(); -} - - -void -mem_mapping_del(mem_mapping_t *map) -{ - mem_mapping_t *ptr; - - /* Disable the entry. */ - mem_mapping_disable(map); - - /* Zap it from the list. */ - for (ptr = &base_mapping; ptr->next != NULL; ptr = ptr->next) { - if (ptr->next == map) { - ptr->next = map->next; - break; - } - } -} - - -void -mem_mapping_add(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) -{ - mem_mapping_t *dest = &base_mapping; - - /* Add mapping to the end of the list.*/ - while (dest->next) - dest = dest->next; - dest->next = map; - map->prev = dest; - - if (size) - map->enable = 1; - else - map->enable = 0; - map->base = base; - map->size = size; - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - map->exec = exec; - map->flags = fl; - map->p = p; - map->dev = NULL; - map->next = NULL; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_handler(mem_mapping_t *map, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)) -{ - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) -{ - /* Remove old mapping. */ - map->enable = 0; - mem_mapping_recalc(map->base, map->size); - - /* Set new mapping. */ - map->enable = 1; - map->base = base; - map->size = size; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) -{ - map->exec = exec; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_set_p(mem_mapping_t *map, void *p) -{ - map->p = p; -} - - -void -mem_mapping_set_dev(mem_mapping_t *map, void *p) -{ - map->dev = p; -} - - -void -mem_mapping_disable(mem_mapping_t *map) -{ - map->enable = 0; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_mapping_enable(mem_mapping_t *map) -{ - map->enable = 1; - - mem_mapping_recalc(map->base, map->size); -} - - -void -mem_set_mem_state(uint32_t base, uint32_t size, int state) -{ - uint32_t c; - - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) - _mem_state[(c + base) >> MEM_GRANULARITY_BITS] = state; - - mem_mapping_recalc(base, size); -} - - -void -mem_add_bios(void) -{ - if (biosmask > 0x1ffff) { - /* 256k+ BIOS'es only have low mappings at E0000-FFFFF. */ - mem_mapping_add(&bios_mapping, 0xe0000, 0x20000, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - &rom[0x20000], MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state(0x0e0000, 0x20000, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } else { - mem_mapping_add(&bios_mapping, biosaddr, biosmask + 1, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state(biosaddr, biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } - - if (AT) { - mem_mapping_add(&bios_high_mapping, biosaddr | (cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - mem_read_bios,mem_read_biosw,mem_read_biosl, - mem_write_null,mem_write_nullw,mem_write_nulll, - rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM|MEM_MAPPING_ROMCS, 0); - - mem_set_mem_state(biosaddr | (cpu_16bitbus ? 0x00f00000 : 0xfff00000), biosmask + 1, - MEM_READ_ROMCS | MEM_WRITE_ROMCS); - } -} - - -void -mem_a20_init(void) -{ - if (AT) { - rammask = cpu_16bitbus ? 0xefffff : 0xffefffff; - flushmmucache(); - mem_a20_state = mem_a20_key | mem_a20_alt; - } else { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - } -} - - -/* Reset the memory state. */ -void -mem_reset(void) -{ - uint32_t c, m; - - m = 1024UL * mem_size; - if (ram != NULL) { - free(ram); - ram = NULL; - } - ram = (uint8_t *)malloc(m); /* allocate and clear the RAM block */ - memset(ram, 0x00, m); - - /* - * Allocate the page table based on how much RAM we have. - * We re-allocate the table on each (hard) reset, as the - * memory amount could have changed. - */ - if (AT) { - if (cpu_16bitbus) { - /* 80186/286; maximum address space is 16MB. */ - m = 4096; - } else { - /* 80386+; maximum address space is 4GB. */ - m = (mem_size + 384) >> 2; - if ((m << 2) < (mem_size + 384)) - m++; - if (m < 4096) - m = 4096; - } - } else { - /* 8088/86; maximum address space is 1MB. */ - m = 256; - } - - /* - * Allocate and initialize the (new) page table. - * We only do this if the size of the page table has changed. - */ -#if DYNAMIC_TABLES -mem_log("MEM: reset: previous pages=%08lx, pages_sz=%i\n", pages, pages_sz); -#endif - if (pages_sz != m) { - pages_sz = m; - if (pages) { - free(pages); - pages = NULL; - } - pages = (page_t *)malloc(m*sizeof(page_t)); -#if DYNAMIC_TABLES -mem_log("MEM: reset: new pages=%08lx, pages_sz=%i\n", pages, pages_sz); -#endif - -#if DYNAMIC_TABLES - /* Allocate the (new) lookup tables. */ - if (page_lookup != NULL) free(page_lookup); - page_lookup = (page_t **)malloc(pages_sz*sizeof(page_t *)); - - if (readlookup2 != NULL) free(readlookup2); - readlookup2 = malloc(pages_sz*sizeof(uintptr_t)); - - if (writelookup2 != NULL) free(writelookup2); - writelookup2 = malloc(pages_sz*sizeof(uintptr_t)); - -#endif - } - -#if DYNAMIC_TABLES - memset(page_lookup, 0x00, pages_sz * sizeof(page_t *)); -#else - memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); -#endif - - memset(pages, 0x00, pages_sz*sizeof(page_t)); - - - if (byte_dirty_mask) { - free(byte_dirty_mask); - byte_dirty_mask = NULL; - } - byte_dirty_mask = malloc((mem_size * 1024) / 8); - memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); - - if (byte_code_present_mask) { - free(byte_code_present_mask); - byte_code_present_mask = NULL; - } - byte_code_present_mask = malloc((mem_size * 1024) / 8); - memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); - - for (c = 0; c < pages_sz; c++) { - pages[c].mem = &ram[c << 12]; - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; - } - - memset(_mem_exec, 0x00, sizeof(_mem_exec)); - - memset(&base_mapping, 0x00, sizeof(base_mapping)); - - memset(_mem_state, 0x00, sizeof(_mem_state)); - - mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x0c0000, 0x40000, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - mem_mapping_add(&ram_low_mapping, 0x00000, - (mem_size > 640) ? 0xa0000 : mem_size * 1024, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram, MEM_MAPPING_INTERNAL, NULL); - - if (mem_size > 1024) { - if (cpu_16bitbus && mem_size > 16256) { - mem_set_mem_state(0x100000, (16256 - 1024) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((16256 - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } else { - mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_high_mapping, 0x100000, - ((mem_size - 1024) * 1024), - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - } - } - - if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, - mem_read_ram,mem_read_ramw,mem_read_raml, - mem_write_ram,mem_write_ramw,mem_write_raml, - ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); - - mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, - mem_read_remapped,mem_read_remappedw,mem_read_remappedl, - mem_write_remapped,mem_write_remappedw,mem_write_remappedl, - ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); - - mem_a20_init(); -} - - -void -mem_init(void) -{ - /* Perform a one-time init. */ - ram = rom = NULL; - pages = NULL; -#if DYNAMIC_TABLES - page_lookup = NULL; - readlookup2 = NULL; - writelookup2 = NULL; - -#else - /* Allocate the lookup tables. */ - page_lookup = (page_t **)malloc((1<<20)*sizeof(page_t *)); - - readlookup2 = malloc((1<<20)*sizeof(uintptr_t)); - - writelookup2 = malloc((1<<20)*sizeof(uintptr_t)); -#endif - -#if FIXME - memset(ff_array, 0xff, sizeof(ff_array)); -#endif - - /* Reset the memory state. */ - mem_reset(); -} - - -void -mem_remap_top(int kb) -{ - int c; - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int offset, size = mem_size - 640; - - mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); - if (mem_size <= 640) return; - - if (kb == 0) { - /* Called to disable the mapping. */ - mem_mapping_disable(&ram_remapped_mapping); - - return; - } - - if (size > kb) - size = kb; - - for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { - offset = c - ((start * 1024) >> 12); - pages[c].mem = &ram[0xA0000 + (offset << 12)]; - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64]; - } - - mem_set_mem_state(start * 1024, size * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + (start * 1024)); - - flushmmucache(); -} - -void -mem_reset_page_blocks(void) -{ - uint32_t c; - - if (pages == NULL) return; - - for (c = 0; c < pages_sz; c++) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - pages[c].block = BLOCK_INVALID; - pages[c].block_2 = BLOCK_INVALID; - } -} - - -void -mem_a20_recalc(void) -{ - int state; - - if (! AT) { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - - return; - } - - state = mem_a20_key | mem_a20_alt; - if (state && !mem_a20_state) { - rammask = (AT && cpu_16bitbus) ? 0xffffff : 0xffffffff; - flushmmucache(); - } else if (!state && mem_a20_state) { - rammask = (AT && cpu_16bitbus) ? 0xefffff : 0xffefffff; - flushmmucache(); - } - - mem_a20_state = state; -} diff --git a/src/mouse_bus.c b/src/mouse_bus.c index 36b039d28..df7794adf 100644 --- a/src/mouse_bus.c +++ b/src/mouse_bus.c @@ -75,7 +75,7 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "pic.h" #include "timer.h" #include "device.h" diff --git a/src/mouse_ps2.c b/src/mouse_ps2.c index cb7653664..cbd3e5695 100644 --- a/src/mouse_ps2.c +++ b/src/mouse_ps2.c @@ -143,6 +143,27 @@ ps2_write(uint8_t val, void *priv) keyboard_at_adddata_mouse(dev->sample_rate); break; + case 0xeb: /* Get mouse data */ + keyboard_at_adddata_mouse(0xfa); + + temp = 0; + if (dev->x < 0) + temp |= 0x10; + if (dev->y < 0) + temp |= 0x20; + if (mouse_buttons & 1) + temp |= 1; + if (mouse_buttons & 2) + temp |= 2; + if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) + temp |= 4; + keyboard_at_adddata_mouse(temp); + keyboard_at_adddata_mouse(dev->x & 0xff); + keyboard_at_adddata_mouse(dev->y & 0xff); + if (dev->flags & FLAG_INTMODE) + keyboard_at_adddata_mouse(dev->z); + break; + case 0xf2: /* read ID */ keyboard_at_adddata_mouse(0xfa); if (dev->flags & FLAG_INTMODE) @@ -169,6 +190,7 @@ ps2_write(uint8_t val, void *priv) case 0xff: /* reset */ dev->mode = MODE_STREAM; dev->flags &= 0x88; + mouse_queue_start = mouse_queue_end = 0; keyboard_at_adddata_mouse(0xfa); keyboard_at_adddata_mouse(0xaa); keyboard_at_adddata_mouse(0x00); diff --git a/src/mouse_serial.c b/src/mouse_serial.c index c96a7598d..b306e1252 100644 --- a/src/mouse_serial.c +++ b/src/mouse_serial.c @@ -623,6 +623,7 @@ ltsermouse_write(struct serial_s *serial, void *priv, uint8_t data) switch (data) { default: mouse_serial_log("Serial mouse: Invalid period %02X, using 1200 bps\n", data); + /*FALLTHROUGH*/ case 0x6E: dev->transmit_period = sermouse_transmit_period(dev, 1200, -1); break; diff --git a/src/network.rar b/src/network.rar new file mode 100644 index 000000000..363c66769 Binary files /dev/null and b/src/network.rar differ diff --git a/src/network/net_3c503.c b/src/network/net_3c503.c index 282219ab3..51084ed79 100644 --- a/src/network/net_3c503.c +++ b/src/network/net_3c503.c @@ -48,13 +48,13 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../mem.h" -#include "../random.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "mem.h" +#include "random.h" +#include "device.h" #include "network.h" #include "net_dp8390.h" #include "net_3c503.h" @@ -617,7 +617,7 @@ threec503_nic_init(const device_t *info) dev->regs.gacfr = 0x09; /* Start with RAM mapping enabled. */ /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx); + network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); return(dev); } diff --git a/src/network/net_dp8390.c b/src/network/net_dp8390.c index 3c30a23e5..4b1fa3edd 100644 --- a/src/network/net_dp8390.c +++ b/src/network/net_dp8390.c @@ -7,7 +7,7 @@ * Emulation of the DP8390 Network Interface Controller used by * the WD family, NE1000/NE2000 family, and 3Com 3C503 NIC's. * - * Version: @(#)net_dp8390.c 1.0.2 2018/10/21 + * Version: @(#)net_dp8390.c 1.0.3 2020/03/23 * * Authors: Miran Grca, * Bochs project, @@ -23,8 +23,8 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" +#include "86box.h" +#include "device.h" #include "network.h" #include "net_dp8390.h" @@ -204,7 +204,7 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) /* Check for start-tx */ if ((val & 0x04) && dev->TCR.loop_cntl) { if (dev->TCR.loop_cntl) { - dp8390_rx(dev, &dev->mem[(dev->tx_page_start * 256) - dev->mem_start], + dp8390_rx(dev, dev->mem, dev->tx_bytes); } } else if (val & 0x04) { @@ -224,7 +224,7 @@ dp8390_write_cr(dp8390_t *dev, uint32_t val) /* Send the packet to the system driver */ dev->CR.tx_packet = 1; - network_tx(&dev->mem[(dev->tx_page_start * 256) - dev->mem_start], dev->tx_bytes); + network_tx(dev->mem, dev->tx_bytes); /* some more debug */ #ifdef ENABLE_DP8390_LOG @@ -388,7 +388,7 @@ dp8390_rx(void *priv, uint8_t *buf, int io_len) pkthdr[0], pkthdr[1], pkthdr[2], pkthdr[3]); /* Copy into buffer, update curpage, and signal interrupt if config'd */ - startptr = &dev->mem[(dev->curr_page * 256) - dev->mem_start]; + startptr = dev->mem + ((dev->curr_page * 256) - dev->mem_start); memcpy(startptr, pkthdr, sizeof(pkthdr)); if ((nextpage > dev->curr_page) || ((dev->curr_page + pages) == dev->page_stop)) { @@ -396,7 +396,7 @@ dp8390_rx(void *priv, uint8_t *buf, int io_len) } else { endbytes = (dev->page_stop - dev->curr_page) * 256; memcpy(startptr+sizeof(pkthdr), buf, endbytes-sizeof(pkthdr)); - startptr = &dev->mem[(dev->page_start * 256) - dev->mem_start]; + startptr = dev->mem + ((dev->page_start * 256) - dev->mem_start); memcpy(startptr, buf+endbytes-sizeof(pkthdr), io_len-endbytes+8); } dev->curr_page = nextpage; diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index 0fd45626c..8feb13c5c 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -52,15 +52,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../mca.h" -#include "../pci.h" -#include "../pic.h" -#include "../random.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "mca.h" +#include "pci.h" +#include "pic.h" +#include "random.h" +#include "device.h" #include "network.h" #include "net_dp8390.h" #include "net_ne2000.h" @@ -1465,7 +1465,7 @@ nic_init(const device_t *info) nic_reset(dev); /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx); + network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); nelog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); diff --git a/src/network/net_pcap.c b/src/network/net_pcap.c index 5acc9c170..6ca9a2fe3 100644 --- a/src/network/net_pcap.c +++ b/src/network/net_pcap.c @@ -51,11 +51,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_dynld.h" -// #include "../ui.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "plat_dynld.h" #include "network.h" @@ -185,7 +184,7 @@ poll_thread(void *arg) if (pcap == NULL) break; /* Wait for the next packet to arrive. */ - if (network_get_wait()) + if (network_get_wait() || (poll_card->wait && poll_card->wait(poll_card->priv))) data = NULL; else data = (uint8_t *)f_pcap_next((void *)pcap, &h); @@ -260,10 +259,16 @@ net_pcap_prepare(netdev_t *list) } for (dev=devlist; dev!=NULL; dev=dev->next) { - strcpy(list->device, dev->name); - if (dev->description) - strcpy(list->description, dev->description); - else + if (strlen(dev->name) <= 127) + strcpy(list->device, dev->name); + else + strncpy(list->device, dev->name, 127); + if (dev->description) { + if (strlen(dev->description) <= 127) + strcpy(list->description, dev->description); + else + strncpy(list->description, dev->description, 127); + } else memset(list->description, '\0', sizeof(list->description)); list++; i++; } diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index fa5cab9d6..d2e20acd3 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -7,7 +7,7 @@ * Emulation of the AMD PCnet LANCE NIC controller for both the ISA, VLB, * and PCI buses. * - * Version: @(#)net_pcnet.c 1.0.0 2019/11/09 + * Version: @(#)net_pcnet.c 1.0.1 2020/03/23 * * Authors: Miran Grca, * TheCollector1995, @@ -31,21 +31,20 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../dma.h" -#include "../mem.h" -#include "../rom.h" -#include "../pci.h" -#include "../pic.h" -#include "../random.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "mem.h" +#include "rom.h" +#include "pci.h" +#include "pic.h" +#include "random.h" +#include "device.h" #include "network.h" #include "net_pcnet.h" #include "bswap.h" - /* PCI info. */ #define PCI_VENDID 0x1022 /* AMD */ #define PCI_DEVID 0x2000 /* PCnet-PCI II (Am79c970A) */ @@ -119,37 +118,37 @@ typedef struct RTNETETHERHDR /** @name Bus configuration sub register accessors. * @{ */ -#define BCR_DWIO(S) ((S)->aBCR[BCR_BSBC] & 0x0080) -#define BCR_SSIZE32(S) ((S)->aBCR[BCR_SWS ] & 0x0100) +#define BCR_DWIO(S) !!((S)->aBCR[BCR_BSBC] & 0x0080) +#define BCR_SSIZE32(S) !!((S)->aBCR[BCR_SWS ] & 0x0100) #define BCR_SWSTYLE(S) ((S)->aBCR[BCR_SWS ] & 0x00FF) /** @} */ /** @name CSR subregister accessors. * @{ */ -#define CSR_INIT(S) ((S)->aCSR[0] & 0x0001) /**< Init assertion */ -#define CSR_STRT(S) ((S)->aCSR[0] & 0x0002) /**< Start assertion */ -#define CSR_STOP(S) ((S)->aCSR[0] & 0x0004) /**< Stop assertion */ -#define CSR_TDMD(S) ((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */ -#define CSR_TXON(S) ((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */ -#define CSR_RXON(S) ((S)->aCSR[0] & 0x0020) /**< Receive On */ -#define CSR_INEA(S) ((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */ -#define CSR_LAPPEN(S) ((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */ -#define CSR_DXSUFLO(S) ((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */ -#define CSR_ASTRP_RCV(S) ((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */ -#define CSR_DPOLL(S) ((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */ -#define CSR_SPND(S) ((S)->aCSR[5] & 0x0001) /**< Suspend */ -#define CSR_LTINTEN(S) ((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */ -#define CSR_TOKINTD(S) ((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */ +#define CSR_INIT(S) !!((S)->aCSR[0] & 0x0001) /**< Init assertion */ +#define CSR_STRT(S) !!((S)->aCSR[0] & 0x0002) /**< Start assertion */ +#define CSR_STOP(S) !!((S)->aCSR[0] & 0x0004) /**< Stop assertion */ +#define CSR_TDMD(S) !!((S)->aCSR[0] & 0x0008) /**< Transmit demand. (perform xmit poll now (readable, settable, not clearable) */ +#define CSR_TXON(S) !!((S)->aCSR[0] & 0x0010) /**< Transmit on (readonly) */ +#define CSR_RXON(S) !!((S)->aCSR[0] & 0x0020) /**< Receive On */ +#define CSR_INEA(S) !!((S)->aCSR[0] & 0x0040) /**< Interrupt Enable */ +#define CSR_LAPPEN(S) !!((S)->aCSR[3] & 0x0020) /**< Look Ahead Packet Processing Enable */ +#define CSR_DXSUFLO(S) !!((S)->aCSR[3] & 0x0040) /**< Disable Transmit Stop on Underflow error */ +#define CSR_ASTRP_RCV(S) !!((S)->aCSR[4] & 0x0400) /**< Auto Strip Receive */ +#define CSR_DPOLL(S) !!((S)->aCSR[4] & 0x1000) /**< Disable Transmit Polling */ +#define CSR_SPND(S) !!((S)->aCSR[5] & 0x0001) /**< Suspend */ +#define CSR_LTINTEN(S) !!((S)->aCSR[5] & 0x4000) /**< Last Transmit Interrupt Enable */ +#define CSR_TOKINTD(S) !!((S)->aCSR[5] & 0x8000) /**< Transmit OK Interrupt Disable */ -#define CSR_STINT ((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */ -#define CSR_STINTE ((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */ +#define CSR_STINT !!((S)->aCSR[7] & 0x0800) /**< Software Timer Interrupt */ +#define CSR_STINTE !!((S)->aCSR[7] & 0x0400) /**< Software Timer Interrupt Enable */ -#define CSR_DRX(S) ((S)->aCSR[15] & 0x0001) /**< Disable Receiver */ -#define CSR_DTX(S) ((S)->aCSR[15] & 0x0002) /**< Disable Transmit */ -#define CSR_LOOP(S) ((S)->aCSR[15] & 0x0004) /**< Loopback Enable */ -#define CSR_DRCVPA(S) ((S)->aCSR[15] & 0x2000) /**< Disable Receive Physical Address */ -#define CSR_DRCVBC(S) ((S)->aCSR[15] & 0x4000) /**< Disable Receive Broadcast */ -#define CSR_PROM(S) ((S)->aCSR[15] & 0x8000) /**< Promiscuous Mode */ +#define CSR_DRX(S) !!((S)->aCSR[15] & 0x0001) /**< Disable Receiver */ +#define CSR_DTX(S) !!((S)->aCSR[15] & 0x0002) /**< Disable Transmit */ +#define CSR_LOOP(S) !!((S)->aCSR[15] & 0x0004) /**< Loopback Enable */ +#define CSR_DRCVPA(S) !!((S)->aCSR[15] & 0x2000) /**< Disable Receive Physical Address */ +#define CSR_DRCVBC(S) !!((S)->aCSR[15] & 0x4000) /**< Disable Receive Broadcast */ +#define CSR_PROM(S) !!((S)->aCSR[15] & 0x8000) /**< Promiscuous Mode */ /** @name CSR register accessors. * @{ */ @@ -193,14 +192,14 @@ typedef struct { mem_mapping_t mmio_mapping; const char *name; int board; - int is_pci, is_vlb; + int is_pci, is_vlb, is_isa; int PCIBase; int MMIOBase; uint32_t base_address; int base_irq; - int dma_channel; - int card; /* PCI card slot */ - int xmit_pos; + int dma_channel; + int card; /* PCI card slot */ + int xmit_pos; /** Register Address Pointer */ uint32_t u32RAP; /** Internal interrupt service */ @@ -214,6 +213,7 @@ typedef struct { uint8_t aPROM[16]; uint16_t aCSR[CSR_MAX_REG]; uint16_t aBCR[BCR_MAX_RAP]; + uint16_t aMII[MII_MAX_REG]; /** The loopback transmit buffer (avoid stack allocations). */ uint8_t abLoopBuf[4096]; /** The recv buffer. */ @@ -222,14 +222,18 @@ typedef struct { int iLog2DescSize; /** Bits 16..23 in 16-bit mode */ uint32_t GCUpperPhys; + /** We are waiting/about to start waiting for more receive buffers. */ + int fMaybeOutOfSpace; /** True if we signal the guest that RX packets are missing. */ int fSignalRxMiss; /** Link speed to be reported through CSR68. */ uint32_t u32LinkSpeed; /** Error counter for bad receive descriptors. */ uint32_t uCntBadRMD; - uint8_t maclocal[6]; /* configured MAC (local) address */ - pc_timer_t poll_timer; + uint16_t u16CSR0LastSeenByGuest; + uint64_t last_poll; + uint8_t maclocal[6]; /* configured MAC (local) address */ + pc_timer_t poll_timer, timer_soft_int; } nic_t; /** @todo All structs: big endian? */ @@ -359,10 +363,10 @@ static void pcnetAsyncTransmit(nic_t *dev); static void pcnetPollRxTx(nic_t *dev); static void pcnetPollTimer(nic_t *dev); static void pcnetUpdateIrq(nic_t *dev); -static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap); -static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val); -static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val); -static void pcnetCanReceive(nic_t *dev); +static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap); +static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val); +static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val); +static int pcnetCanReceive(nic_t *dev); #ifdef ENABLE_PCNET_LOG @@ -400,7 +404,6 @@ pcnet_do_irq(nic_t *dev, int issue) } } - /** * Load transmit message descriptor * Make sure we read the own flag first. @@ -794,14 +797,14 @@ pcnetTdraAddr(nic_t *dev, int idx) static void pcnetSoftReset(nic_t *dev) { - pcnetlog(3, "%s: pcnetSoftReset\n", dev->name); + pcnetlog(3, "%s: pcnetSoftReset\n", dev->name); dev->u32Lnkst = 0x40; dev->GCRDRA = 0; dev->GCTDRA = 0; dev->u32RAP = 0; - dev->aCSR[0] = 0x0004; + dev->aCSR[0] = 0x0004; dev->aCSR[3] = 0x0000; dev->aCSR[4] = 0x0115; dev->aCSR[5] = 0x0000; @@ -818,14 +821,25 @@ pcnetSoftReset(nic_t *dev) CSR_XMTRC(dev) = 1; CSR_RCVRL(dev) = 1; CSR_XMTRL(dev) = 1; - dev->aCSR[80] = 0x1410; - if (dev->is_pci) { - dev->aCSR[88] = 0x1003; - dev->aCSR[89] = 0x0262; - } else { - dev->aCSR[88] = 0x3003; - dev->aCSR[89] = 0x0000; - } + dev->aCSR[80] = 0x1410; + + switch (dev->board) { + case DEV_AM79C970A: + dev->aCSR[88] = 0x1003; + dev->aCSR[89] = 0x0262; + break; + case DEV_AM79C973: + dev->aCSR[88] = 0x5003; + dev->aCSR[89] = 0x0262; + break; + case DEV_AM79C960: + case DEV_AM79C960_EB: + case DEV_AM79C960_VLB: + dev->aCSR[88] = 0x3003; + dev->aCSR[89] = 0x0262; + break; + } + dev->aCSR[94] = 0x0000; dev->aCSR[100] = 0x0200; dev->aCSR[103] = 0x0105; @@ -839,72 +853,75 @@ pcnetSoftReset(nic_t *dev) static void pcnetUpdateIrq(nic_t *dev) { - dev->iISR = 0; - - dev->aCSR[0] &= ~0x0080; /* clear INTR */ + int iISR = 0; + uint16_t csr0; - if ((!(dev->aCSR[3] & 0x4000) && (dev->aCSR[0] & 0x4000)) /* BABL */ || - (!(dev->aCSR[3] & 0x1000) && (dev->aCSR[0] & 0x1000)) /* MISS */ || - (!(dev->aCSR[3] & 0x0100) && (dev->aCSR[0] & 0x0100)) /* IDON */ || - (!(dev->aCSR[3] & 0x0200) && (dev->aCSR[0] & 0x0200)) /* TINT */ || - (!(dev->aCSR[3] & 0x0400) && (dev->aCSR[0] & 0x0400)) /* RINT */ || - (!(dev->aCSR[3] & 0x0800) && (dev->aCSR[0] & 0x0800)) /* MERR */ || - (!(dev->aCSR[4] & 0x0001) && (dev->aCSR[4] & 0x0002)) /* JAB */ || - (!(dev->aCSR[4] & 0x0004) && (dev->aCSR[4] & 0x0008)) /* TXSTRT */ || - (!(dev->aCSR[4] & 0x0010) && (dev->aCSR[4] & 0x0020)) /* RCVO */ || - (!(dev->aCSR[4] & 0x0100) && (dev->aCSR[4] & 0x0200)) /* MFCO */ || - ((dev->aCSR[5] & 0x0040) && (dev->aCSR[5] & 0x0080)) /* EXDINT */ || - ((dev->aCSR[5] & 0x0008) && (dev->aCSR[5] & 0x0010)) /* MPINT */) { - dev->iISR = CSR_INEA(dev); /* CSR_INEA */ - dev->aCSR[0] |= 0x0080; /* set INTR */ + csr0 = dev->aCSR[0]; + + csr0 &= ~0x0080; /* clear INTR */ + + if (((csr0 & ~dev->aCSR[3]) & 0x5f00) || + (((dev->aCSR[4]>>1) & ~dev->aCSR[4]) & 0x0115) || + (((dev->aCSR[5]>>1) & dev->aCSR[5]) & 0x0048)) { + iISR = !!(csr0 & 0x0040); /* CSR_INEA */ + csr0 |= 0x0080; /* set INTR */ } - - if (dev->aCSR[4] & 0x0080) { /* UINT */ - dev->aCSR[4] &= ~0x0080; - dev->aCSR[4] |= 0x0040; - dev->iISR = 1; /* CSR_INEA */ - dev->aCSR[0] |= 0x0080; /* set INTR */ - pcnetlog(3, "%s: user int\n", dev->name); - } - - if (((dev->aCSR[5] & 0x0400) && (dev->aCSR[5] & 0x0800)) /* SINT */ || - ((dev->aCSR[5] & 0x0100) && (dev->aCSR[5] & 0x0200)) /* SLPINT */ ) { - dev->iISR = 1; /* CSR_INEA */ - dev->aCSR[0] |= 0x0080; /* set INTR */ + + if (dev->aCSR[4] & 0x0080) { /* UINTCMD */ + dev->aCSR[4] &= ~0x0080; /* clear UINTCMD */ + dev->aCSR[4] |= 0x0040; /* set UINT */ + pcnetlog(2, "%s: user int\n", dev->name); } - pcnetlog(3, "%s: pcnetUpdateIrq: set irq isr=%02x, TINT=%04x\n", dev->name, !!dev->iISR, dev->aCSR[0] & 0x0200); - + if (dev->aCSR[4] & csr0 & 0x0040 /* CSR_INEA */) { + csr0 |= 0x0080; /* set INTR */ + iISR = 1; + } + + if (((dev->aCSR[5]>>1) & dev->aCSR[5]) & 0x0500) { + iISR = 1; + csr0 |= 0x0080; /* set INTR */ + } + + if ((dev->aCSR[7] & 0x0c00) == 0x0c00) /* STINT + STINTE */ + iISR = 1; + + dev->aCSR[0] = csr0; + + pcnetlog(2, "%s: pcnetUpdateIrq: iISR=%d\n", dev->name, iISR); + /* normal path is to _not_ change the IRQ status */ - if (dev->iISR) - pcnet_do_irq(dev, 1); + if (iISR != dev->iISR) { + pcnet_do_irq(dev, iISR); + dev->iISR = iISR; + } } static void pcnetInit(nic_t *dev) { - int i; + int i; pcnetlog(3, "%s: pcnetInit: init_addr=%#010x\n", dev->name, PHYSADDR(dev, CSR_IADR(dev))); /** @todo Documentation says that RCVRL and XMTRL are stored as two's complement! * Software is allowed to write these registers directly. */ #define PCNET_INIT() do { \ - DMAPageRead(PHYSADDR(dev, CSR_IADR(dev)), \ - (uint8_t *)&initblk, sizeof(initblk)); \ - dev->aCSR[15] = le32_to_cpu(initblk.mode); \ - CSR_RCVRL(dev) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ - CSR_XMTRL(dev) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ - dev->aCSR[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ - dev->aCSR[ 8] = le32_to_cpu(initblk.ladrf1); \ - dev->aCSR[ 9] = le32_to_cpu(initblk.ladrf2); \ - dev->aCSR[10] = le32_to_cpu(initblk.ladrf3); \ - dev->aCSR[11] = le32_to_cpu(initblk.ladrf4); \ - dev->aCSR[12] = le32_to_cpu(initblk.padr1); \ - dev->aCSR[13] = le32_to_cpu(initblk.padr2); \ - dev->aCSR[14] = le32_to_cpu(initblk.padr3); \ - dev->GCRDRA = PHYSADDR(dev, initblk.rdra); \ - dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ + DMAPageRead(PHYSADDR(dev, CSR_IADR(dev)), \ + (uint8_t *)&initblk, sizeof(initblk)); \ + dev->aCSR[15] = le16_to_cpu(initblk.mode); \ + CSR_RCVRL(dev) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ + CSR_XMTRL(dev) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ + dev->aCSR[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ + dev->aCSR[ 8] = le16_to_cpu(initblk.ladrf1); \ + dev->aCSR[ 9] = le16_to_cpu(initblk.ladrf2); \ + dev->aCSR[10] = le16_to_cpu(initblk.ladrf3); \ + dev->aCSR[11] = le16_to_cpu(initblk.ladrf4); \ + dev->aCSR[12] = le16_to_cpu(initblk.padr1); \ + dev->aCSR[13] = le16_to_cpu(initblk.padr2); \ + dev->aCSR[14] = le16_to_cpu(initblk.padr3); \ + dev->GCRDRA = PHYSADDR(dev, initblk.rdra); \ + dev->GCTDRA = PHYSADDR(dev, initblk.tdra); \ } while (0) if (BCR_SSIZE32(dev)) { @@ -923,7 +940,7 @@ pcnetInit(nic_t *dev) #undef PCNET_INIT - int cbRxBuffers = 0; + size_t cbRxBuffers = 0; for (i = CSR_RCVRL(dev); i >= 1; i--) { RMD rmd; uint32_t rdaddr = PHYSADDR(dev, pcnetRdraAddr(dev, i)); @@ -950,7 +967,7 @@ pcnetInit(nic_t *dev) * usually 1536 bytes and should therefore not run into condition. If they are still * short in RX buffers we notify this condition. */ - dev->fSignalRxMiss = (cbRxBuffers == 0 || cbRxBuffers >= 32*128); + dev->fSignalRxMiss = (cbRxBuffers == 0 || cbRxBuffers >= 32*1024); CSR_RCVRC(dev) = CSR_RCVRL(dev); CSR_XMTRC(dev) = CSR_XMTRL(dev); @@ -991,8 +1008,8 @@ pcnetStart(nic_t *dev) if (!CSR_DRX(dev)) dev->aCSR[0] |= 0x0020; /* set RXON */ dev->aCSR[0] &= ~0x0004; /* clear STOP bit */ - dev->aCSR[0] |= 0x0002; /* STRT */ - pcnetPollTimer(dev); + dev->aCSR[0] |= 0x0002; /* STRT */ + pcnetPollTimer(dev); } @@ -1006,7 +1023,7 @@ pcnetStop(nic_t *dev) dev->aCSR[0] = 0x0004; dev->aCSR[4] &= ~0x02c2; dev->aCSR[5] &= ~0x0011; - pcnetPollTimer(dev); + pcnetPollTimer(dev); } @@ -1015,7 +1032,6 @@ pcnetStop(nic_t *dev) * Note: Once a descriptor belongs to the network card (this driver), it cannot be changed * by the host (the guest driver) anymore. Well, it could but the results are undefined by * definition. - * @param fSkipCurrent if true, don't scan the current RDTE. */ static void pcnetRdtePoll(nic_t *dev) @@ -1034,27 +1050,26 @@ pcnetRdtePoll(nic_t *dev) if (i < 1) i = CSR_RCVRL(dev); - addr = pcnetRdraAddr(dev, i); - CSR_CRDA(dev) = CSR_CRBA(dev) = 0; - CSR_CRBC(dev) = CSR_CRST(dev) = 0; - if (!pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, addr), 1)) - return; - if (!IS_RMD_BAD(rmd)) { - CSR_CRDA(dev) = addr; /* Receive Descriptor Address */ - CSR_CRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ - CSR_CRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ - CSR_CRST(dev) = ((uint32_t *)&rmd)[1] >> 16; /* Receive Status */ - pcnetCanReceive(dev); - } else { - /* This is not problematic since we don't own the descriptor - * We actually do own it, otherwise pcnetRmdLoad would have returned false. - * Don't flood the release log with errors. - */ - if (++dev->uCntBadRMD < 50) - pcnetlog(1, "%s: BAD RMD ENTRIES AT %#010x (i=%d)\n", - dev->name, addr, i); - return; - } + addr = pcnetRdraAddr(dev, i); + CSR_CRDA(dev) = CSR_CRBA(dev) = 0; + CSR_CRBC(dev) = CSR_CRST(dev) = 0; + if (!pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, addr), 1)) + return; + if (!IS_RMD_BAD(rmd)) { + CSR_CRDA(dev) = addr; /* Receive Descriptor Address */ + CSR_CRBA(dev) = rmd.rmd0.rbadr; /* Receive Buffer Address */ + CSR_CRBC(dev) = rmd.rmd1.bcnt; /* Receive Byte Count */ + CSR_CRST(dev) = ((uint32_t *)&rmd)[1] >> 16; /* Receive Status */ + } else { + /* This is not problematic since we don't own the descriptor + * We actually do own it, otherwise pcnetRmdLoad would have returned false. + * Don't flood the release log with errors. + */ + if (++dev->uCntBadRMD < 50) + pcnetlog(1, "%s: BAD RMD ENTRIES AT %#010x (i=%d)\n", + dev->name, addr, i); + return; + } /* * The next descriptor. @@ -1186,13 +1201,12 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) { nic_t *dev = (nic_t *)priv; int is_padr = 0, is_bcast = 0, is_ladr = 0; - uint32_t iRxDesc; - int cbPacket; - uint8_t buf1[60]; - + uint32_t iRxDesc; + int cbPacket; + uint8_t buf1[60]; if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev) || !size) - return; + return; /* if too small buffer, then expand it */ if (size < 60) { @@ -1215,16 +1229,16 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) || (is_bcast = padr_bcast(dev, buf, size)) || (is_ladr = ladr_match(dev, buf, size))) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); if (HOST_IS_OWNER(CSR_CRST(dev))) { /* Not owned by controller. This should not be possible as * we already called pcnetCanReceive(). */ - const uint32_t cb = 1 << dev->iLog2DescSize; + const unsigned cb = 1 << dev->iLog2DescSize; uint32_t GCPhys = dev->GCRDRA; iRxDesc = CSR_RCVRL(dev); - + while (iRxDesc-- > 0) { RMD rmd; pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, GCPhys), 0); @@ -1232,11 +1246,11 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) } dev->aCSR[0] |= 0x1000; /* Set MISS flag */ CSR_MISSC(dev)++; - pcnetlog(2, "%s: pcnetReceiveNoSync: packet missed\n", dev->name); + pcnetlog(2, "%s: pcnetReceiveNoSync: packet missed\n", dev->name); } else { - RTNETETHERHDR *pEth = (RTNETETHERHDR *)buf; + RTNETETHERHDR *pEth = (RTNETETHERHDR *)buf; int fStrip = 0; - int len_802_3; + size_t len_802_3; uint8_t *src = &dev->abRecvBuf[8]; uint32_t crda = CSR_CRDA(dev); uint32_t next_crda; @@ -1251,40 +1265,40 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) * * NB: CSR_ASTRP_RCV bit affects only 802.3 frames! */ - len_802_3 = cpu_to_be16(pEth->EtherType); + len_802_3 = cpu_to_be16(pEth->EtherType); if (len_802_3 < 46 && CSR_ASTRP_RCV(dev)) { size = MIN(sizeof(RTNETETHERHDR) + len_802_3, size); fStrip = 1; } - - memcpy(src, buf, size); - + + memcpy(src, buf, size); + if (!fStrip) { /* In loopback mode, Runt Packed Accept is always enabled internally; * don't do any padding because guest may be looping back very short packets. */ - if (!CSR_LOOP(dev)) - while (size < 60) - src[size++] = 0; + if (!CSR_LOOP(dev)) + while (size < 60) + src[size++] = 0; + + uint32_t fcs = UINT32_MAX; + uint8_t *p = src; - uint32_t fcs = UINT32_MAX; - uint8_t *p = src; + while (p != &src[size]) + CRC(fcs, *p++); - while (p != &src[size]) - CRC(fcs, *p++); + /* FCS at the end of the packet */ + ((uint32_t *)&src[size])[0] = htonl(fcs); + size += 4; + } - /* FCS at the end of the packet */ - ((uint32_t *)&src[size])[0] = htonl(fcs); - size += 4; - } - - cbPacket = size; + cbPacket = (int)size; pcnetRmdLoad(dev, &rmd, PHYSADDR(dev, crda), 0); /* if (!CSR_LAPPEN(dev)) */ rmd.rmd1.stp = 1; - int cbBuf = MIN(4096 - rmd.rmd1.bcnt, size); + size_t cbBuf = MIN(4096 - rmd.rmd1.bcnt, size); uint32_t rbadr = PHYSADDR(dev, rmd.rmd0.rbadr); /* save the old value to check if it was changed as long as we didn't @@ -1305,9 +1319,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) /* RX disabled in the meantime? If so, abort RX. */ if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) { - pcnetlog(3, "%s: RX disabled 1\n", dev->name); + pcnetlog(3, "%s: RX disabled 1\n", dev->name); return; - } + } /* Was the register modified in the meantime? If so, don't touch the * register but still update the RX descriptor. */ @@ -1318,9 +1332,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) } else iRxDesc = CSR_RCVRC(dev); - src += cbBuf; - size -= cbBuf; - + src += cbBuf; + size -= cbBuf; + while (size > 0) { /* Read the entire next descriptor as we're likely to need it. */ next_crda = pcnetRdraAddr(dev, iRxDesc); @@ -1338,7 +1352,7 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) crda = next_crda; rmd = next_rmd; - cbBuf = MIN(4096 - rmd.rmd1.bcnt, size); + cbBuf = MIN(4096 - (size_t)rmd.rmd1.bcnt, size); uint32_t rbadr2 = PHYSADDR(dev, rmd.rmd0.rbadr); /* We have to leave the critical section here or we risk deadlocking @@ -1348,9 +1362,9 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) /* RX disabled in the meantime? If so, abort RX. */ if (CSR_DRX(dev) || CSR_STOP(dev) || CSR_SPND(dev)) { - pcnetlog(3, "%s: RX disabled 2\n", dev->name); + pcnetlog(3, "%s: RX disabled 2\n", dev->name); return; - } + } /* Was the register modified in the meantime? If so, don't touch the * register but still update the RX descriptor. */ @@ -1360,10 +1374,10 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) CSR_RCVRC(dev) = iRxDesc; } else { iRxDesc = CSR_RCVRC(dev); - } + } - src += cbBuf; - size -= cbBuf; + src += cbBuf; + size -= cbBuf; } if (size == 0) { @@ -1374,7 +1388,7 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) rmd.rmd2.mcnt = cbPacket; rmd.rmd2.zeros = 0; } else { - pcnetlog(2, "%s: Overflow by %ubytes\n", dev->name, size); + pcnetlog(1, "%s: Overflow by %ubytes\n", dev->name, size); rmd.rmd1.oflo = 1; rmd.rmd1.buff = 1; rmd.rmd1.err = 1; @@ -1384,18 +1398,15 @@ pcnetReceiveNoSync(void *priv, uint8_t *buf, int size) pcnetRmdStorePassHost(dev, &rmd, PHYSADDR(dev, crda)); dev->aCSR[0] |= 0x0400; - pcnetlog(2, "%s: RINT set, RCVRC=%d CRDA=%#010x\n", dev->name, + pcnetlog(1, "%s: RINT set, RCVRC=%d CRDA=%#010x\n", dev->name, CSR_RCVRC(dev), PHYSADDR(dev, CSR_CRDA(dev))); /* guest driver is owner: force repoll of current and next RDTEs */ CSR_CRST(dev) = 0; - } } + } - if (!CSR_LOOP(dev)) - pcnetPollRxTx(dev); - - pcnetUpdateIrq(dev); + pcnetUpdateIrq(dev); } @@ -1418,7 +1429,8 @@ pcnetAsyncTransmit(nic_t *dev) /* * Iterate the transmit descriptors. */ - int cMax = 32; + unsigned cFlushIrq = 0; + int cMax = 32; do { TMD tmd; if (!pcnetTdtePoll(dev, &tmd)) @@ -1433,52 +1445,55 @@ pcnetAsyncTransmit(nic_t *dev) */ if (tmd.tmd1.stp && tmd.tmd1.enp) { const int cb = 4096 - tmd.tmd1.bcnt; - pcnetlog(1, "%s: pcnetAsyncTransmit: stp&enp: cb=%d xmtrc=%#x\n", dev->name, cb, CSR_XMTRC(dev)); - dev->xmit_pos = cb; - DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb); - - if (fLoopback) { - /* From the manual: ``A zero length buffer is acceptable as - * long as it is not the last buffer in a chain (STP = 0 and - * ENP = 1).'' That means that the first buffer might have a - * zero length if it is not the last one in the chain. */ - if (cb <= MAX_FRAME) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); - - pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); - } else if (cb == 4096) { - /* The Windows NT4 pcnet driver sometimes marks the first - * unused descriptor as owned by us. Ignore that (by - * passing it back). Do not update the ring counter in this - * case (otherwise that driver becomes even more confused, - * which causes transmit to stall for about 10 seconds). - * This is just a workaround, not a final solution. */ - /* r=frank: IMHO this is the correct implementation. The - * manual says: ``If the OWN bit is set and the buffer - * length is 0, the OWN bit will be cleared. In the C-LANCE - * the buffer length of 0 is interpreted as a 4096-byte - * buffer.'' */ - /* r=michaln: Perhaps not quite right. The C-LANCE (Am79C90) - * datasheet explains that the old LANCE (Am7990) ignored - * the top four bits next to BCNT and a count of 0 was - * interpreted as 4096. In the C-LANCE, that is still the - * case if the top bits are all ones. If all 16 bits are - * zero, the C-LANCE interprets it as zero-length transmit - * buffer. It's not entirely clear if the later models - * (PCnet-ISA, PCnet-PCI) behave like the C-LANCE or not. - * It is possible that the actual behavior of the C-LANCE - * and later hardware is that the buffer lengths are *16-bit* - * two's complement numbers between 0 and 4096. AMD's drivers - * in fact generally treat the length as a 16-bit quantity. */ - pcnetlog(1, "%s: pcnetAsyncTransmit: illegal 4kb frame -> ignoring\n", dev->name); - pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); - break; - } - } else { - pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp\n", dev->name); - network_tx(dev->abLoopBuf, dev->xmit_pos); - } + pcnetlog("%s: pcnetAsyncTransmit: stp&enp: cb=%d xmtrc=%#x\n", dev->name, cb, CSR_XMTRC(dev)); + + /* From the manual: ``A zero length buffer is acceptable as + * long as it is not the last buffer in a chain (STP = 0 and + * ENP = 1).'' That means that the first buffer might have a + * zero length if it is not the last one in the chain. */ + if (cb <= MAX_FRAME) { + dev->xmit_pos = cb; + DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb); + + if (fLoopback) { + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); + + pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); + } else { + pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp and enp, xmit pos = %d\n", dev->name, dev->xmit_pos); + network_tx(dev->abLoopBuf, dev->xmit_pos); + } + } else if (cb == 4096) { + /* The Windows NT4 pcnet driver sometimes marks the first + * unused descriptor as owned by us. Ignore that (by + * passing it back). Do not update the ring counter in this + * case (otherwise that driver becomes even more confused, + * which causes transmit to stall for about 10 seconds). + * This is just a workaround, not a final solution. + */ + /* r=frank: IMHO this is the correct implementation. The + * manual says: ``If the OWN bit is set and the buffer + * length is 0, the OWN bit will be cleared. In the C-LANCE + * the buffer length of 0 is interpreted as a 4096-byte + * buffer.'' + */ + /* r=michaln: Perhaps not quite right. The C-LANCE (Am79C90) + * datasheet explains that the old LANCE (Am7990) ignored + * the top four bits next to BCNT and a count of 0 was + * interpreted as 4096. In the C-LANCE, that is still the + * case if the top bits are all ones. If all 16 bits are + * zero, the C-LANCE interprets it as zero-length transmit + * buffer. It's not entirely clear if the later models + * (PCnet-ISA, PCnet-PCI) behave like the C-LANCE or not. + * It is possible that the actual behavior of the C-LANCE + * and later hardware is that the buffer lengths are *16-bit* + * two's complement numbers between 0 and 4096. AMD's drivers + * in fact generally treat the length as a 16-bit quantity. */ + pcnetlog(1, "%s: pcnetAsyncTransmit: illegal 4kb frame -> ignoring\n", dev->name); + pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); + break; + } /* Write back the TMD and pass it to the host (clear own bit). */ pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); @@ -1488,7 +1503,7 @@ pcnetAsyncTransmit(nic_t *dev) CSR_XMTRC(dev) = CSR_XMTRL(dev); } else { CSR_XMTRC(dev)--; - } + } } else if (tmd.tmd1.stp) { /* * Read TMDs until end-of-packet or tdte poll fails (underflow). @@ -1497,19 +1512,10 @@ pcnetAsyncTransmit(nic_t *dev) * waste time finding out how much space we actually need even if * we could reliably do that on SMP guests. */ - int cb = 4096 - tmd.tmd1.bcnt; - dev->xmit_pos = pcnetCalcPacketLen(dev, cb); - DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb); - if (fLoopback) { - if (HOST_IS_OWNER(CSR_CRST(dev))) - pcnetRdtePoll(dev); - pcnetlog(3, "%s: pcnetAsyncTransmit: receive loopback stp\n", dev->name); - pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); - } else { - pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf stp\n", dev->name); - network_tx(dev->abLoopBuf, dev->xmit_pos); - } - + unsigned cb = 4096 - tmd.tmd1.bcnt; + dev->xmit_pos = pcnetCalcPacketLen(dev, cb); + DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf, cb); + for (;;) { /* * Advance the ring counter register and check the next tmd. @@ -1527,6 +1533,8 @@ pcnetAsyncTransmit(nic_t *dev) */ tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1; dev->aCSR[0] |= 0x0200; /* set TINT */ + /* Don't allow the guest to clear TINT before reading it */ + dev->u16CSR0LastSeenByGuest &= ~0x0200; if (!CSR_DXSUFLO(dev)) /* stop on xmit underflow */ dev->aCSR[0] &= ~0x0010; /* clear TXON */ pcnetTmdStorePassHost(dev, &tmd, GCPhysPrevTmd); @@ -1543,22 +1551,25 @@ pcnetAsyncTransmit(nic_t *dev) pcnetTmdLoad(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev)), 0); cb = 4096 - tmd.tmd1.bcnt; if (dev->xmit_pos + cb <= MAX_FRAME) { /** @todo this used to be ... + cb < MAX_FRAME. */ - int off = dev->xmit_pos; - dev->xmit_pos = cb + off; - DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf + off, cb); - } + int off = dev->xmit_pos; + dev->xmit_pos = cb + off; + DMAPageRead(PHYSADDR(dev, tmd.tmd0.tbadr), dev->abLoopBuf + off, cb); + } /* * Done already? */ if (tmd.tmd1.enp) { - if (fLoopback) { - pcnetlog(3, "%s: pcnetAsyncTransmit: receive loopback enp\n", dev->name); - pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); - } else { - pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name); - network_tx(dev->abLoopBuf, dev->xmit_pos); - } + if (fLoopback) { + if (HOST_IS_OWNER(CSR_CRST(dev))) + pcnetRdtePoll(dev); + + pcnetlog(3, "%s: pcnetAsyncTransmit: receive loopback enp\n", dev->name); + pcnetReceiveNoSync(dev, dev->abLoopBuf, dev->xmit_pos); + } else { + pcnetlog(3, "%s: pcnetAsyncTransmit: transmit loopbuf enp\n", dev->name); + network_tx(dev->abLoopBuf, dev->xmit_pos); + } /* Write back the TMD, pass it to the host */ pcnetTmdStorePassHost(dev, &tmd, PHYSADDR(dev, CSR_CXDA(dev))); @@ -1574,16 +1585,23 @@ pcnetAsyncTransmit(nic_t *dev) } /* Update TDMD, TXSTRT and TINT. */ dev->aCSR[0] &= ~0x0008; /* clear TDMD */ - dev->aCSR[4] |= 0x0008; /* set TXSTRT */ - if ( !CSR_TOKINTD(dev) /* Transmit OK Interrupt Disable, no infl. on errors. */ - || (CSR_LTINTEN(dev) && tmd.tmd1.ltint) - || tmd.tmd1.err) { - dev->aCSR[0] |= 0x0200; /* set TINT */ - pcnetUpdateIrq(dev); + dev->aCSR[4] |= 0x0008; /* set TXSTRT */ + dev->xmit_pos = -1; + if (!CSR_TOKINTD(dev) /* Transmit OK Interrupt Disable, no infl. on errors. */ + || (CSR_LTINTEN(dev) && tmd.tmd1.ltint) + || tmd.tmd1.err) { + cFlushIrq++; } if (--cMax == 0) break; } while (CSR_TXON(dev)); /* transfer on */ + + if (cFlushIrq) { + dev->aCSR[0] |= 0x0200; /* set TINT */ + /* Don't allow the guest to clear TINT before reading it */ + dev->u16CSR0LastSeenByGuest &= ~0x0200; + pcnetUpdateIrq(dev); + } } @@ -1599,7 +1617,7 @@ pcnetPollRxTx(nic_t *dev) * true but pcnetCanReceive() returned false for some other reason we need to check * _now_ if we have to wakeup pcnetWaitReceiveAvail(). */ - if (HOST_IS_OWNER(CSR_CRST(dev))) + if (HOST_IS_OWNER(CSR_CRST(dev)) || dev->fMaybeOutOfSpace) pcnetRdtePoll(dev); } @@ -1616,8 +1634,8 @@ pcnetPollTimer(nic_t *dev) pcnetUpdateIrq(dev); - if (!CSR_STOP(dev) && !CSR_SPND(dev) && !CSR_DPOLL(dev)) - pcnetPollRxTx(dev); + if (!CSR_STOP(dev) && !CSR_SPND(dev) && (!CSR_DPOLL(dev) || dev->fMaybeOutOfSpace)) + pcnetPollRxTx(dev); } @@ -1626,27 +1644,37 @@ pcnetHardReset(nic_t *dev) { pcnetlog(2, "%s: pcnetHardReset\n", dev->name); + dev->iISR = 0; + pcnet_do_irq(dev, 0); + + /* Many of the BCR values would normally be read from the EEPROM. */ dev->aBCR[BCR_MSRDA] = 0x0005; dev->aBCR[BCR_MSWRA] = 0x0005; - dev->aBCR[BCR_MC ] = 0x0002; + dev->aBCR[BCR_MC] = 0x0002; dev->aBCR[BCR_LNKST] = 0x00c0; - dev->aBCR[BCR_LED1 ] = 0x0084; - dev->aBCR[BCR_LED2 ] = 0x0088; - dev->aBCR[BCR_LED3 ] = 0x0090; + dev->aBCR[BCR_LED1] = 0x0084; + dev->aBCR[BCR_LED2] = 0x0088; + dev->aBCR[BCR_LED3] = 0x0090; - /* For ISA PnP cards, BCR8 reports IRQ/DMA (e.g. 0x0035 means IRQ 3, DMA 5). */ - if (dev->board == PCNET_ISA) - dev->aBCR[8] = (dev->dma_channel) | (dev->base_irq << 4); - - dev->aBCR[BCR_FDC ] = 0x0000; - dev->aBCR[BCR_BSBC ] = 0x9001; + /* For ISA PnP cards, BCR8 reports IRQ/DMA (e.g. 0x0035 means IRQ 3, DMA 5). */ + if (dev->is_isa) + dev->aBCR[8] = dev->dma_channel | (dev->base_irq << 4); + + dev->aBCR[BCR_FDC] = 0x0000; + dev->aBCR[BCR_BSBC] = 0x9001; dev->aBCR[BCR_EECAS] = 0x0002; - dev->aBCR[BCR_SWS ] = 0x0200; - dev->iLog2DescSize = 3; - dev->aBCR[BCR_PLAT ] = 0xff06; - + dev->aBCR[BCR_STVAL] = 0xffff; + dev->aCSR[58] = dev->aBCR[BCR_SWS] = 0x0200; /* CSR58 is an alias for BCR20 */ + dev->iLog2DescSize = 3; + dev->aBCR[BCR_PLAT] = 0xff06; + dev->aBCR[BCR_MIICAS] = 0x20; /* Auto-negotiation on. */ + dev->aBCR[BCR_MIIADDR] = 0; /* Internal PHY on Am79C973 would be (0x1e << 5) */ + dev->aBCR[BCR_PCIVID] = 0x1022; + dev->aBCR[BCR_PCISID] = 0x0020; + dev->aBCR[BCR_PCISVID] = 0x1022; + /* Reset the error counter. */ - dev->uCntBadRMD = 0; + dev->uCntBadRMD = 0; pcnetSoftReset(dev); } @@ -1655,53 +1683,50 @@ pcnetHardReset(nic_t *dev) static void pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val) { - uint16_t old_inea = CSR_INEA(dev); - pcnetlog(1, "%s: pcnet_csr_writew: rap=%d val=%#06x\n", dev->name, rap, val); switch (rap) { case 0: - /* Clear any interrupt flags. */ - dev->aCSR[0] &= ~(val & 0x7f00); - dev->aCSR[0] = (dev->aCSR[0] & ~0x0040) | (val & 0x0048); - val = (val & 0x007f) | (dev->aCSR[0] & 0x7f00); + { + uint16_t csr0 = dev->aCSR[0]; + /* Clear any interrupt flags. + * Don't clear an interrupt flag which was not seen by the guest yet. */ + csr0 &= ~(val & 0x7f00 & dev->u16CSR0LastSeenByGuest); + csr0 = (csr0 & ~0x0040) | (val & 0x0048); + val = (val & 0x007f) | (csr0 & 0x7f00); - /* If STOP, STRT and INIT are set, clear STRT and INIT */ - if ((val & 7) == 7) - val &= ~3; + /* If STOP, STRT and INIT are set, clear STRT and INIT */ + if ((val & 7) == 7) + val &= ~3; - pcnetlog(2, "%s: CSR0 val = %04x, val2 = %04x\n", dev->name, val, dev->aCSR[0]); + pcnetlog(2, "%s: CSR0 val = %04x, val2 = %04x\n", dev->name, val, dev->aCSR[0]); - if (old_inea && !(val & 0x40)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Disable IRQ\n", dev->name); - dev->iISR = 0; - dev->aCSR[0] &= ~0x0080; - pcnet_do_irq(dev, 0); - } + dev->aCSR[0] = csr0; - if (!CSR_STOP(dev) && (val & 4)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Stop\n", dev->name); - pcnetStop(dev); - } + if (!CSR_STOP(dev) && (val & 4)) { + pcnetlog(3, "%s: pcnet_csr_writew(): Stop\n", dev->name); + pcnetStop(dev); + } - if (!CSR_INIT(dev) && (val & 1)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Init\n", dev->name); - pcnetInit(dev); - } + if (!CSR_INIT(dev) && (val & 1)) { + pcnetlog(3, "%s: pcnet_csr_writew(): Init\n", dev->name); + pcnetInit(dev); + } - if (!CSR_STRT(dev) && (val & 2)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Start\n", dev->name); - pcnetStart(dev); - } + if (!CSR_STRT(dev) && (val & 2)) { + pcnetlog(3, "%s: pcnet_csr_writew(): Start\n", dev->name); + pcnetStart(dev); + } - if (CSR_TDMD(dev)) { - pcnetlog(3, "%s: pcnet_csr_writew(): Transmit\n", dev->name); - pcnetAsyncTransmit(dev); - } + if (CSR_TDMD(dev)) { + pcnetlog(3, "%s: pcnet_csr_writew(): Transmit\n", dev->name); + pcnetAsyncTransmit(dev); + } + } + return; - return; case 2: /* IADRH */ - if (dev->board == PCNET_ISA) - val &= 0x00ff; /* Upper 8 bits ignored on ISA chips. */ + if (dev->is_isa) + val &= 0x00ff; /* Upper 8 bits ignored on ISA chips. */ case 1: /* IADRL */ case 8: /* LADRF 0..15 */ case 9: /* LADRF 16..31 */ @@ -1739,66 +1764,79 @@ pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val) case 72: /* RCVRC */ case 74: /* XMTRC */ case 112: /* MISSC */ - if (CSR_STOP(dev) || CSR_SPND(dev)) - break; - return; + if (CSR_STOP(dev) || CSR_SPND(dev)) + break; + return; case 3: /* Interrupt Mask and Deferral Control */ - break; + break; case 4: /* Test and Features Control */ - dev->aCSR[4] &= ~(val & 0x026a); - val &= ~0x026a; - val |= dev->aCSR[4] & 0x026a; - break; - case 5: /* Extended Control and Interrupt 1 */ - dev->aCSR[5] &= ~(val & 0x0a90); - val &= ~0x0a90; - val |= dev->aCSR[5] & 0x0a90; - break; - case 16: - pcnet_csr_writew(dev,1,val); - return; - case 17: - pcnet_csr_writew(dev,2,val); - return; + dev->aCSR[4] &= ~(val & 0x026a); + val &= ~0x026a; + val |= dev->aCSR[4] & 0x026a; + break; + case 5: /* Extended Control and Interrupt 1 */ + dev->aCSR[5] &= ~(val & 0x0a90); + val &= ~0x0a90; + val |= dev->aCSR[5] & 0x0a90; + break; + case 7: /* Extended Control and Interrupt 2 */ + { + uint16_t csr7 = dev->aCSR[7]; + csr7 &= ~0x0400; + csr7 &= ~(val & 0x0800); + csr7 |= (val & 0x0400); + dev->aCSR[7] = csr7; + } + return; + case 15: /* Mode */ + break; + case 16: /* IADRL */ + pcnet_csr_writew(dev,1,val); + return; + case 17: /* IADRH */ + pcnet_csr_writew(dev,2,val); + return; /* * 24 and 25 are the Base Address of Receive Descriptor. * We combine and mirror these in GCRDRA. */ case 24: /* BADRL */ case 25: /* BADRU */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x, ignoring!!\n", dev->name, rap, val); - return; - } - if (rap == 24) - dev->GCRDRA = (dev->GCRDRA & 0xffff0000) | (val & 0x0000ffff); - else - dev->GCRDRA = (dev->GCRDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); - pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCRDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCRDRA); - if (dev->GCRDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned RDRA (GCRDRA=%#010x)\n", dev->name, dev->GCRDRA); - break; + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnetlog(3, "%s: WRITE CSR%d, %#06x, ignoring!!\n", dev->name, rap, val); + return; + } + if (rap == 24) + dev->GCRDRA = (dev->GCRDRA & 0xffff0000) | (val & 0x0000ffff); + else + dev->GCRDRA = (dev->GCRDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); + pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCRDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCRDRA); + if (dev->GCRDRA & (dev->iLog2DescSize - 1)) + pcnetlog(1, "%s: Warning: Misaligned RDRA (GCRDRA=%#010x)\n", dev->name, dev->GCRDRA); + break; /* * 30 & 31 are the Base Address of Transmit Descriptor. * We combine and mirrorthese in GCTDRA. */ case 30: /* BADXL */ case 31: /* BADXU */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); - return; - } - if (rap == 30) - dev->GCTDRA = (dev->GCTDRA & 0xffff0000) | (val & 0x0000ffff); - else - dev->GCTDRA = (dev->GCTDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); - pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCTDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCTDRA); - if (dev->GCTDRA & (dev->iLog2DescSize - 1)) - pcnetlog(1, "%s: Warning: Misaligned TDRA (GCTDRA=%#010x)\n", dev->name, dev->GCTDRA); - break; + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); + return; + } + if (rap == 30) + dev->GCTDRA = (dev->GCTDRA & 0xffff0000) | (val & 0x0000ffff); + else + dev->GCTDRA = (dev->GCTDRA & 0x0000ffff) | ((val & 0x0000ffff) << 16); + + pcnetlog(3, "%s: WRITE CSR%d, %#06x => GCTDRA=%08x (alt init)\n", dev->name, rap, val, dev->GCTDRA); + + if (dev->GCTDRA & (dev->iLog2DescSize - 1)) + pcnetlog(1, "%s: Warning: Misaligned TDRA (GCTDRA=%#010x)\n", dev->name, dev->GCTDRA); + break; case 58: /* Software Style */ - pcnet_bcr_writew(dev,BCR_SWS,val); - break; + pcnet_bcr_writew(dev,BCR_SWS,val); + break; /* * Registers 76 and 78 aren't stored correctly (see todos), but I'm don't dare * try fix that right now. So, as a quick hack for 'alt init' I'll just correct them here. @@ -1807,21 +1845,21 @@ pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val) /** @todo receive ring length is stored in two's complement! */ case 78: /* XMTRL */ /** @todo call pcnetUpdateRingHandlers */ /** @todo transmit ring length is stored in two's complement! */ - if (!CSR_STOP(dev) && !CSR_SPND(dev)) { - pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); - return; - } - pcnetlog(3, "%s: WRITE CSR%d, %#06x (hacked %#06x) (alt init)\n", dev->name, - rap, val, 1 + ~val); - val = 1 + ~val; - - /* - * HACK ALERT! Set the counter registers too. - */ - dev->aCSR[rap - 4] = val; - break; - default: + if (!CSR_STOP(dev) && !CSR_SPND(dev)) { + pcnetlog(3, "%s: WRITE CSR%d, %#06x !!\n", dev->name, rap, val); return; + } + pcnetlog(3, "%s: WRITE CSR%d, %#06x (hacked %#06x) (alt init)\n", dev->name, + rap, val, 1 + ~val); + val = 1 + ~val; + + /* + * HACK ALERT! Set the counter registers too. + */ + dev->aCSR[rap - 4] = val; + break; + default: + return; } dev->aCSR[rap] = val; @@ -1831,10 +1869,10 @@ pcnet_csr_writew(nic_t *dev, uint16_t rap, uint16_t val) /** * Encode a 32-bit link speed into a custom 16-bit floating-point value */ -static uint16_t +static uint16_t pcnetLinkSpd(uint32_t speed) { - unsigned exp = 0; + unsigned exp = 0; while (speed & 0xFFFFE000) { speed /= 10; @@ -1851,62 +1889,64 @@ pcnet_csr_readw(nic_t *dev, uint16_t rap) switch (rap) { case 0: - pcnetUpdateIrq(dev); - val = dev->aCSR[0]; - val |= (val & 0x7800) ? 0x8000 : 0; - break; + pcnetUpdateIrq(dev); + val = dev->aCSR[0]; + val |= (val & 0x7800) ? 0x8000 : 0; + dev->u16CSR0LastSeenByGuest = val; + break; case 16: - return pcnet_csr_readw(dev,1); + return pcnet_csr_readw(dev,1); case 17: - return pcnet_csr_readw(dev,2); + return pcnet_csr_readw(dev,2); case 58: - return pcnet_bcr_readw(dev,BCR_SWS); - case 68: /* Custom register to pass link speed to driver */ - return pcnetLinkSpd(dev->u32LinkSpeed); + return pcnet_bcr_readw(dev,BCR_SWS); + case 68: /* Custom register to pass link speed to driver */ + return pcnetLinkSpd(dev->u32LinkSpeed); case 88: - val = dev->aCSR[89]; - val <<= 16; - val |= dev->aCSR[88]; - break; + val = dev->aCSR[89]; + val <<= 16; + val |= dev->aCSR[88]; + break; default: - val = dev->aCSR[rap]; - break; + val = dev->aCSR[rap]; + break; } pcnetlog(3, "%s: pcnet_csr_readw rap=%d val=0x%04x\n", dev->name, rap, val); return val; } -static void +static void pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val) { rap &= 0x7f; pcnetlog(3, "%s: pcnet_bcr_writew rap=%d val=0x%04x\n", dev->name, rap, val); switch (rap) { case BCR_SWS: - if (!(CSR_STOP(dev) || CSR_SPND(dev))) - return; - val &= ~0x0300; - switch (val & 0x00ff) { - default: - case 0: - val |= 0x0200; /* 16 bit */ - dev->iLog2DescSize = 3; - dev->GCUpperPhys = (0xff00 & dev->aCSR[2]) << 16; - break; - case 1: - val |= 0x0100; /* 32 bit */ - dev->iLog2DescSize = 4; - dev->GCUpperPhys = 0; - break; - case 2: - case 3: - val |= 0x0300; /* 32 bit */ - dev->iLog2DescSize = 4; - dev->GCUpperPhys = 0; - break; - } - /* fall through */ + if (!(CSR_STOP(dev) || CSR_SPND(dev))) + return; + val &= ~0x0300; + switch (val & 0x00ff) { + default: + case 0: + val |= 0x0200; /* 16 bit */ + dev->iLog2DescSize = 3; + dev->GCUpperPhys = (0xff00 & dev->aCSR[2]) << 16; + break; + case 1: + val |= 0x0100; /* 32 bit */ + dev->iLog2DescSize = 4; + dev->GCUpperPhys = 0; + break; + case 2: + case 3: + val |= 0x0300; /* 32 bit */ + dev->iLog2DescSize = 4; + dev->GCUpperPhys = 0; + break; + } + dev->aCSR[58] = val; + /* fall through */ case BCR_LNKST: case BCR_LED1: case BCR_LED2: @@ -1916,13 +1956,156 @@ pcnet_bcr_writew(nic_t *dev, uint16_t rap, uint16_t val) case BCR_BSBC: case BCR_EECAS: case BCR_PLAT: - dev->aBCR[rap] = val; - break; + case BCR_MIICAS: + case BCR_MIIADDR: + dev->aBCR[rap] = val; + break; + + case BCR_STVAL: + val &= 0xffff; + dev->aBCR[BCR_STVAL] = val; + if (dev->board == DEV_AM79C973) + timer_set_delay_u64(&dev->timer_soft_int, (12.8 * val) * TIMER_USEC); + break; + + case BCR_MIIMDR: + dev->aMII[dev->aBCR[BCR_MIIADDR] & 0x1f] = val; + break; + default: - break; + break; } } +static uint16_t +pcnet_mii_readw(nic_t *dev, uint16_t miiaddr) +{ + uint16_t val; + int autoneg, duplex, fast, isolate; + + /* If the DANAS (BCR32.7) bit is set, the MAC does not do any + * auto-negotiation and the PHY must be set up explicitly. DANAS + * effectively disables most other BCR32 bits. + */ + if (dev->aBCR[BCR_MIICAS] & 0x80) { + /* PHY controls auto-negotiation. */ + autoneg = duplex = fast = 1; + } else { + /* BCR32 controls auto-negotiation. */ + autoneg = (dev->aBCR[BCR_MIICAS] & 0x20) != 0; + duplex = (dev->aBCR[BCR_MIICAS] & 0x10) != 0; + fast = (dev->aBCR[BCR_MIICAS] & 0x08) != 0; + } + + /* Electrically isolating the PHY mostly disables it. */ + isolate = (dev->aMII[0] & 0x400) != 0; + + switch (miiaddr) { + case 0: + /* MII basic mode control register. */ + val = 0; + if (autoneg) + val |= 0x1000; /* Enable auto negotiation. */ + if (fast) + val |= 0x2000; /* 100 Mbps */ + if (duplex) /* Full duplex forced */ + val |= 0x0100; /* Full duplex */ + if (isolate) /* PHY electrically isolated. */ + val |= 0x0400; /* Isolated */ + break; + + case 1: + /* MII basic mode status register. */ + val = 0x7800 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0040 /* Mgmt frame preamble not required. */ + | 0x0020 /* Auto-negotiation complete. */ + | 0x0008 /* Able to do auto-negotiation. */ + | 0x0004 /* Link up. */ + | 0x0001; /* Extended Capability, i.e. registers 4+ valid. */ + if (isolate) { + val &= ~(0x0020 | 0x0004); + } + if (!autoneg) { + /* Auto-negotiation disabled. */ + if (duplex) + val &= ~0x2800; /* Full duplex forced. */ + else + val &= ~0x5000; /* Half duplex forced. */ + + if (fast) + val &= ~0x1800; /* 100 Mbps forced */ + else + val &= ~0x6000; /* 10 Mbps forced */ + } + break; + + case 2: + /* PHY identifier 1. */ + val = 0x22; /* Am79C874/AC101 PHY */ + break; + + case 3: + /* PHY identifier 2. */ + val = 0x561b; /* Am79C874/AC101 PHY */ + break; + + case 4: + /* Advertisement control register. */ + val = 0x01e0 /* Try 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0001; /* CSMA selector. */ + break; + + case 5: + /* Link partner ability register. */ + if (!isolate) { + val = 0x8000 /* Next page bit. */ + | 0x4000 /* Link partner acked us. */ + | 0x0400 /* Can do flow control. */ + | 0x01e0 /* Can do 100mbps FD/HD and 10mbps FD/HD. */ + | 0x0001; /* Use CSMA selector. */ + } else { + val = 0; + } + break; + + case 6: + /* Auto negotiation expansion register. */ + if (!isolate) { + val = 0x0008 /* Link partner supports npage. */ + | 0x0004 /* Enable npage words. */ + | 0x0001; /* Can do N-way auto-negotiation. */ + } else { + val = 0; + } + break; + + case 18: + /* Diagnostic Register (FreeBSD pcn/ac101 driver reads this). */ + if (!isolate) { + val = 0x1000 /* Receive PLL locked. */ + | 0x0200; /* Signal detected. */ + + if (autoneg) { + val |= 0x0400 /* 100Mbps rate. */ + | 0x0800; /* Full duplex. */ + } else { + if (fast) + val |= 0x0400; /* 100Mbps rate. */ + if (duplex) + val |= 0x0800; /* Full duplex. */ + } + } else { + val = 0; + } + break; + + default: + val = 0; + break; + } + + return val; +} static uint16_t pcnet_bcr_readw(nic_t *dev, uint16_t rap) @@ -1937,6 +2120,14 @@ pcnet_bcr_readw(nic_t *dev, uint16_t rap) val = dev->aBCR[rap] & ~0x8000; val |= (val & 0x017f & dev->u32Lnkst) ? 0x8000 : 0; break; + + case BCR_MIIADDR: + if ((dev->board == DEV_AM79C973) && (((dev->aBCR[BCR_MIIADDR] >> 5) & 0x1f) == 0)) { + uint16_t miiaddr = dev->aBCR[BCR_MIIADDR] & 0x1f; + val = pcnet_mii_readw(dev, miiaddr); + } else + val = 0xffff; + break; default: val = rap < BCR_MAX_RAP ? dev->aBCR[rap] : 0; break; @@ -2385,7 +2576,7 @@ pcnet_pci_read(int func, int addr, void *p) case 0x07: return 2; case 0x08: - return 0x10; /*Revision ID*/ + return (dev->board == DEV_AM79C973) ? 0x40 : 0x10; /*Revision ID*/ case 0x09: return 0; /*Programming interface*/ case 0x0A: @@ -2412,6 +2603,14 @@ pcnet_pci_read(int func, int addr, void *p) return pcnet_pci_bar[1].addr_regs[2]; case 0x17: return pcnet_pci_bar[1].addr_regs[3]; + case 0x2C: + return 0x22; + case 0x2D: + return 0x10; + case 0x2E: + return 0x00; + case 0x2F: + return 0x20; case 0x3C: return dev->base_irq; case 0x3D: @@ -2435,9 +2634,11 @@ pcnet_pci_read(int func, int addr, void *p) * @returns VBox status code. * @param pThis The PCnet instance data. */ -static void +static int pcnetCanReceive(nic_t *dev) { + int rc = 0; + if (!CSR_DRX(dev) && !CSR_STOP(dev) && !CSR_SPND(dev)) { if (HOST_IS_OWNER(CSR_CRST(dev)) && dev->GCRDRA) pcnetRdtePoll(dev); @@ -2446,11 +2647,47 @@ pcnetCanReceive(nic_t *dev) /** @todo Notify the guest _now_. Will potentially increase the interrupt load */ if (dev->fSignalRxMiss) dev->aCSR[0] |= 0x1000; /* Set MISS flag */ - } + } else + rc = 1; } + + return rc; } +static int +pcnetWaitReceiveAvail(void *priv) +{ + nic_t *dev = (nic_t *) priv; + + dev->fMaybeOutOfSpace = !pcnetCanReceive(dev); + + return dev->fMaybeOutOfSpace; +} + +static void +pcnetTimerSoftInt(void *priv) +{ + nic_t *dev = (nic_t *) priv; + + dev->aCSR[7] |= 0x0800; /* STINT */ + pcnetUpdateIrq(dev); + timer_advance_u64(&dev->timer_soft_int, (12.8 * (dev->aBCR[BCR_STVAL] & 0xffff)) * TIMER_USEC); +} + +static void +pcnetTimerCallback(void *priv) +{ + nic_t *dev = (nic_t *) priv; + +#ifdef ENABLE_PCNET_LOG + pcnetlog(3, "Timer Callback to RX\n"); +#endif + pcnetPollRxTx(dev); + + timer_disable(&dev->poll_timer); +} + static void * pcnet_init(const device_t *info) { @@ -2475,6 +2712,7 @@ pcnet_init(const device_t *info) dev->is_pci = !!(info->flags & DEVICE_PCI); dev->is_vlb = !!(info->flags & DEVICE_VLB); + dev->is_isa = !!(info->flags & (DEVICE_ISA | DEVICE_AT)); if (dev->is_pci) { pcnet_mem_init(dev, 0x0fffff00); @@ -2510,9 +2748,10 @@ pcnet_init(const device_t *info) dev->aPROM[6] = dev->aPROM[7] = 0x00; /* Reserved Location: must be 00h */ - dev->aPROM[8] = 0x00; + dev->aPROM[8] = 0x00; /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */ + /* 0x00/0xFF=ISA, 0x01=PnP, 0x10=VLB, 0x11=PCI */ if (dev->is_pci) dev->aPROM[9] = 0x11; else if (dev->is_vlb) @@ -2523,13 +2762,14 @@ pcnet_init(const device_t *info) /* User programmable space, init with 0 */ dev->aPROM[10] = dev->aPROM[11] = 0x00; - /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh - and bytes 0Eh and 0Fh, must therefore be initialized with 0! */ - dev->aPROM[12] = dev->aPROM[13] = 0x00; - - /* Must be ASCII W (57h) if compatibility to AMD - driver software is desired */ - dev->aPROM[14] = dev->aPROM[15] = 0x57; + if (dev->board == DEV_AM79C960_EB) { + dev->aPROM[14] = 0x52; + dev->aPROM[15] = 0x44; /* NI6510 EtherBlaster 'RD' signature. */ + } else { + /* Must be ASCII W (57h) if compatibility to AMD + driver software is desired */ + dev->aPROM[14] = dev->aPROM[15] = 0x57; + } for (c = 0, checksum = 0; c < 16; c++) checksum += dev->aPROM[c]; @@ -2559,7 +2799,7 @@ pcnet_init(const device_t *info) dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); if (dev->is_vlb) - dev->dma_channel = 0; + dev->dma_channel = -1; else dev->dma_channel = device_get_config_int("dma"); pcnet_ioset(dev, dev->base_address, 0x20); @@ -2571,13 +2811,18 @@ pcnet_init(const device_t *info) dev->aPROM[3], dev->aPROM[4], dev->aPROM[5]); pcnetlog(1, "%s: %s attached IO=0x%X IRQ=%d\n", dev->name, - dev->is_pci?"PCI":"ISA", dev->base_address, dev->base_irq); + dev->is_pci?"PCI":"VLB/ISA", dev->base_address, dev->base_irq); /* Reset the board. */ pcnetHardReset(dev); /* Attach ourselves to the network module. */ - network_attach(dev, dev->aPROM, pcnetReceiveNoSync); + network_attach(dev, dev->aPROM, pcnetReceiveNoSync, pcnetWaitReceiveAvail); + + if (dev->board == DEV_AM79C973) + timer_add(&dev->timer_soft_int, pcnetTimerSoftInt, dev, 0); + + timer_add(&dev->poll_timer, pcnetTimerCallback, dev, 0); return(dev); } @@ -2589,8 +2834,14 @@ pcnet_close(void *priv) nic_t *dev = (nic_t *)priv; pcnetlog(1, "%s: closed\n", dev->name); - - free(dev); + + if (dev) { + timer_disable(&dev->poll_timer); + + free(dev); + dev = NULL; + + } } @@ -2725,29 +2976,47 @@ static const device_config_t pcnet_vlb_config[] = } }; -const device_t pcnet_pci_device = { - "AMD PCnet-PCI", - DEVICE_PCI, - PCNET_PCI, - pcnet_init, pcnet_close, NULL, - NULL, NULL, NULL, - pcnet_pci_config -}; - -const device_t pcnet_isa_device = { - "AMD PCnet-ISA", +const device_t pcnet_am79c960_device = { + "AMD Am79c960 (PCnet-ISA) ", DEVICE_AT | DEVICE_ISA, - PCNET_ISA, + DEV_AM79C960, pcnet_init, pcnet_close, NULL, NULL, NULL, NULL, pcnet_isa_config }; -const device_t pcnet_vlb_device = { - "AMD PCnet-VL", +const device_t pcnet_am79c960_eb_device = { + "AMD Am79c960EB (PCnet-ISA) ", + DEVICE_AT | DEVICE_ISA, + DEV_AM79C960_EB, + pcnet_init, pcnet_close, NULL, + NULL, NULL, NULL, + pcnet_isa_config +}; + +const device_t pcnet_am79c960_vlb_device = { + "AMD Am79c960 (PCnet-VL) ", DEVICE_VLB, - PCNET_VLB, + DEV_AM79C960_VLB, pcnet_init, pcnet_close, NULL, NULL, NULL, NULL, pcnet_vlb_config }; + +const device_t pcnet_am79c970a_device = { + "AMD Am79c970a (PCnet-PCI II)", + DEVICE_PCI, + DEV_AM79C970A, + pcnet_init, pcnet_close, NULL, + NULL, NULL, NULL, + pcnet_pci_config +}; + +const device_t pcnet_am79c973_device = { + "AMD Am79c973 (PCnet-FAST)", + DEVICE_PCI, + DEV_AM79C973, + pcnet_init, pcnet_close, NULL, + NULL, NULL, NULL, + pcnet_pci_config +}; diff --git a/src/network/net_pcnet.h b/src/network/net_pcnet.h index da4859368..eb6a51d7b 100644 --- a/src/network/net_pcnet.h +++ b/src/network/net_pcnet.h @@ -7,7 +7,7 @@ * Emulation of the AMD PCnet LANCE NIC controller for both the ISA * and PCI buses. * - * Version: @(#)net_pcnet.c 1.0.0 2019/11/09 + * Version: @(#)net_pcnet.c 1.0.1 2020/03/23 * * Authors: Miran Grca, * TheCollector1995, @@ -19,17 +19,20 @@ #ifndef NET_PCNET_H # define NET_PCNET_H - enum { - PCNET_NONE = 0, - PCNET_ISA = 1, /* 16-bit ISA */ - PCNET_PCI = 2, /* 32-bit PCI */ - PCNET_VLB = 3 /* 32-bit VLB */ + DEV_NONE = 0, + DEV_AM79C960 = 1, /* PCnet-ISA (ISA, 10 Mbps, NE2100/NE1500T compatible) */ + DEV_AM79C960_EB = 2, /* PCnet-ISA (ISA, 10 Mbps, Racal InterLan EtherBlaster compatible) */ + DEV_AM79C960_VLB = 3, /* PCnet-VLB (VLB, 10 Mbps, NE2100/NE1500T compatible) */ + DEV_AM79C970A = 4, /* PCnet-PCI II (PCI, 10 Mbps) */ + DEV_AM79C973 = 5 /* PCnet-FAST III (PCI, 10/100 Mbps) */ }; -extern const device_t pcnet_isa_device; -extern const device_t pcnet_pci_device; -extern const device_t pcnet_vlb_device; +extern const device_t pcnet_am79c960_device; +extern const device_t pcnet_am79c960_eb_device; +extern const device_t pcnet_am79c960_vlb_device; +extern const device_t pcnet_am79c970a_device; +extern const device_t pcnet_am79c973_device; #endif /*NET_PCNET_H*/ diff --git a/src/network/net_slirp.c b/src/network/net_slirp.c index 8b8304854..66d26a31b 100644 --- a/src/network/net_slirp.c +++ b/src/network/net_slirp.c @@ -53,10 +53,9 @@ #define HAVE_STDARG_H #include "slirp/slirp.h" #include "slirp/queue.h" -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -// #include "../ui.h" +#include "86box.h" +#include "device.h" +#include "plat.h" #include "network.h" @@ -148,7 +147,7 @@ poll_thread(void *arg) /* Wait for the next packet to arrive. */ data_valid = 0; - if (!network_get_wait() && (QueuePeek(slirpq) != 0)) { + if ((!network_get_wait() && !(poll_card->wait && poll_card->wait(poll_card->priv))) && (QueuePeek(slirpq) != 0)) { /* Grab a packet from the queue. */ // ui_sb_update_icon(SB_NETWORK, 1); diff --git a/src/network/net_wd8003.c b/src/network/net_wd8003.c index 2148a2142..e11fb1e57 100644 --- a/src/network/net_wd8003.c +++ b/src/network/net_wd8003.c @@ -48,16 +48,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../machine/machine.h" -#include "../mca.h" -#include "../pci.h" -#include "../pic.h" -#include "../random.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "machine.h" +#include "mca.h" +#include "pci.h" +#include "pic.h" +#include "random.h" +#include "device.h" #include "network.h" #include "net_dp8390.h" #include "net_wd8003.h" @@ -771,7 +771,7 @@ wd_init(const device_t *info) mem_mapping_disable(&dev->ram_mapping); /* Attach ourselves to the network module. */ - network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx); + network_attach(dev->dp8390, dev->dp8390->physaddr, dp8390_rx, NULL); if (!(dev->board_chip & WE_ID_BUS_MCA)) { wdlog("%s: attached IO=0x%X IRQ=%d, RAM addr=0x%06x\n", dev->name, diff --git a/src/network/network.c b/src/network/network.c index 475a3674e..3b3e08ca5 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -12,7 +12,7 @@ * it should be malloc'ed and then linked to the NETCARD def. * Will be done later. * - * Version: @(#)network.c 1.0.13 2019/12/02 + * Version: @(#)network.c 1.0.14 2020/03/23 * * Author: Fred N. van Kempen, * @@ -55,10 +55,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "ui.h" #include "network.h" #include "net_3c503.h" #include "net_ne2000.h" @@ -71,12 +71,14 @@ static netcard_t net_cards[] = { NULL }, { "[ISA] 3Com EtherLink II (3C503)","3c503", &threec503_device, NULL }, - { "[ISA] AMD PCnet-ISA", "pcnetisa", &pcnet_isa_device, + { "[ISA] AMD PCnet-ISA", "pcnetisa", &pcnet_am79c960_device, NULL }, { "[ISA] Novell NE1000", "ne1k", &ne1000_device, NULL }, { "[ISA] Novell NE2000", "ne2k", &ne2000_device, NULL }, + { "[ISA] Racal Interlan EtherBlaster", "pcnetracal", &pcnet_am79c960_eb_device, + NULL }, { "[ISA] Realtek RTL8019AS", "ne2kpnp", &rtl8019as_device, NULL }, { "[ISA] Western Digital WD8003E", "wd8003e", &wd8003e_device, @@ -91,11 +93,13 @@ static netcard_t net_cards[] = { NULL }, { "[MCA] Western Digital WD8003E/A", "wd8003ea", &wd8003ea_device, NULL }, - { "[PCI] AMD PCnet-PCI", "pcnetpci", &pcnet_pci_device, + { "[PCI] AMD PCnet-FAST III", "pcnetfast", &pcnet_am79c973_device, + NULL }, + { "[PCI] AMD PCnet-PCI II", "pcnetpci", &pcnet_am79c970a_device, NULL }, { "[PCI] Realtek RTL8029AS", "ne2kpci", &rtl8029as_device, NULL }, - { "[VLB] AMD PCnet-VL", "pcnetvlb", &pcnet_vlb_device, + { "[VLB] AMD PCnet-VL", "pcnetvlb", &pcnet_am79c960_vlb_device, NULL }, { "", "", NULL, NULL } @@ -219,13 +223,14 @@ network_init(void) * modules. */ void -network_attach(void *dev, uint8_t *mac, NETRXCB rx) +network_attach(void *dev, uint8_t *mac, NETRXCB rx, NETWAITCB wait) { if (network_card == 0) return; /* Save the card's info. */ net_cards[network_card].priv = dev; net_cards[network_card].rx = rx; + net_cards[network_card].wait = wait; network_mac = mac; network_set_wait(0); diff --git a/src/network/network.h b/src/network/network.h index feae064ee..7edfabf5c 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -65,6 +65,7 @@ enum { typedef void (*NETRXCB)(void *, uint8_t *, int); +typedef int (*NETWAITCB)(void *); typedef struct { @@ -74,6 +75,7 @@ typedef struct { void *priv; int (*poll)(void *); NETRXCB rx; + NETWAITCB wait; } netcard_t; typedef struct { @@ -99,7 +101,7 @@ extern void network_busy(uint8_t set); extern void network_end(void); extern void network_init(void); -extern void network_attach(void *, uint8_t *, NETRXCB); +extern void network_attach(void *, uint8_t *, NETRXCB, NETWAITCB); extern void network_close(void); extern void network_reset(void); extern int network_available(void); diff --git a/src/network/pcap_if.c b/src/network/pcap_if.c index 439dbfa94..b73639b48 100644 --- a/src/network/pcap_if.c +++ b/src/network/pcap_if.c @@ -54,9 +54,9 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" -#include "../plat_dynld.h" +#include "86box.h" +#include "plat.h" +#include "plat_dynld.h" static void *pcap_handle; /* handle to WinPcap DLL */ diff --git a/src/nmi.c b/src/nmi.c index e00061d0c..808113bfa 100644 --- a/src/nmi.c +++ b/src/nmi.c @@ -5,7 +5,7 @@ #include #include #include -#include "io.h" +#include "86box_io.h" #include "nmi.h" diff --git a/src/nvr.c b/src/nvr.c index 53376295f..28b099ba1 100644 --- a/src/nvr.c +++ b/src/nvr.c @@ -55,7 +55,7 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "machine/machine.h" +#include "machine.h" #include "mem.h" #include "timer.h" #include "plat.h" @@ -264,7 +264,8 @@ nvr_load(void) fp = plat_fopen(path, L"rb"); if (fp != NULL) { /* Read NVR contents from file. */ - (void)fread(saved_nvr->regs, saved_nvr->size, 1, fp); + if (fread(saved_nvr->regs, 1, saved_nvr->size, fp) != saved_nvr->size) + fatal("nvr_load(): Error reading data\n"); (void)fclose(fp); } } diff --git a/src/nvr.h b/src/nvr.h index f315b7a51..ce283fe92 100644 --- a/src/nvr.h +++ b/src/nvr.h @@ -8,13 +8,13 @@ * * Definitions for the generic NVRAM/CMOS driver. * - * Version: @(#)nvr.h 1.0.11 2019/03/16 + * Version: @(#)nvr.h 1.0.14 2020/01/24 * * Author: Fred N. van Kempen, , * David HrdliÄka, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2018,2019 David HrdliÄka. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2018-2020 David HrdliÄka. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -50,7 +50,7 @@ # define EMU_NVR_H -#define NVR_MAXSIZE 128 /* max size of NVR data */ +#define NVR_MAXSIZE 256 /* max size of NVR data */ /* Conversion from BCD to Binary and vice versa. */ #define RTC_BCD(x) (((x) % 10) | (((x) / 10) << 4)) @@ -91,6 +91,9 @@ extern const device_t at_nvr_device; extern const device_t ps_nvr_device; extern const device_t amstrad_nvr_device; extern const device_t ibmat_nvr_device; +extern const device_t piix4_nvr_device; +extern const device_t ls486e_nvr_device; +extern const device_t via_nvr_device; #endif @@ -109,5 +112,8 @@ extern int nvr_get_days(int month, int year); extern void nvr_time_get(struct tm *); extern void nvr_time_set(struct tm *); +extern void nvr_at_handler(int set, uint16_t base, nvr_t *nvr); +extern void nvr_wp_set(int set, int h, nvr_t *nvr); + #endif /*EMU_NVR_H*/ diff --git a/src/nvr_at.c b/src/nvr_at.c index 967f14018..cfc3509f5 100644 --- a/src/nvr_at.c +++ b/src/nvr_at.c @@ -189,16 +189,16 @@ * including the later update (DS12887A) which implemented a * "century" register to be compatible with Y2K. * - * Version: @(#)nvr_at.c 1.0.16 2019/11/19 + * Version: @(#)nvr_at.c 1.0.19 2020/01/24 * * Authors: Fred N. van Kempen, * Miran Grca, * Mahod, * Sarah Walker, * - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2016-2019 Miran Grca. - * Copyright 2008-2019 Sarah Walker. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2008-2020 Sarah Walker. * * 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 @@ -226,9 +226,9 @@ #include #include #include "86box.h" -#include "cpu/cpu.h" -#include "machine/machine.h" -#include "io.h" +#include "cpu.h" +#include "machine.h" +#include "86box_io.h" #include "mem.h" #include "nmi.h" #include "pic.h" @@ -281,16 +281,22 @@ # define REGD_VRT 0x80 #define RTC_CENTURY_AT 0x32 /* century register for AT etc */ #define RTC_CENTURY_PS 0x37 /* century register for PS/1 PS/2 */ +#define RTC_ALDAY 0x7D /* VIA VT82C586B - alarm day */ +#define RTC_ALMONTH 0x7E /* VIA VT82C586B - alarm month */ +#define RTC_CENTURY_VIA 0x7F /* century register for VIA VT82C586B */ #define RTC_REGS 14 /* number of registers */ +#define FLAG_LS_HACK 0x01 +#define FLAG_PIIX4 0x02 + typedef struct { int8_t stat; uint8_t cent; - uint8_t def; + uint8_t def, flags; - uint8_t addr; + uint8_t addr[8], wp[2]; int16_t count, state; @@ -301,6 +307,9 @@ typedef struct { } local_t; +static uint8_t nvr_at_inited = 0; + + /* Get the current NVR time. */ static void time_get(nvr_t *nvr, struct tm *tm) @@ -402,6 +411,20 @@ check_alarm(nvr_t *nvr, int8_t addr) } +/* Check for VIA stuff. */ +static int8_t +check_alarm_via(nvr_t *nvr, int8_t addr, int8_t addr_2) +{ + local_t *local = (local_t *)nvr->data; + + if (local->cent == RTC_CENTURY_VIA) { + return((nvr->regs[addr_2] == nvr->regs[addr]) || + ((nvr->regs[addr_2] & AL_DONTCARE) == AL_DONTCARE)); + } else + return 0; +} + + /* Update the NVR registers from the internal clock. */ static void timer_update(void *priv) @@ -425,7 +448,9 @@ timer_update(void *priv) /* Check for any alarms we need to handle. */ if (check_alarm(nvr, RTC_SECONDS) && check_alarm(nvr, RTC_MINUTES) && - check_alarm(nvr, RTC_HOURS)) { + check_alarm(nvr, RTC_HOURS) && + check_alarm_via(nvr, RTC_DOM, RTC_ALDAY) && + check_alarm_via(nvr, RTC_MONTH, RTC_ALMONTH)) { nvr->regs[RTC_REGC] |= REGC_AF; if (nvr->regs[RTC_REGB] & REGB_AIE) { nvr->regs[RTC_REGC] |= REGC_IRQF; @@ -534,13 +559,15 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) nvr_t *nvr = (nvr_t *)priv; local_t *local = (local_t *)nvr->data; struct tm tm; - uint8_t old; + uint8_t old, i; + uint8_t addr_id = (addr & 0x0e) >> 1; + uint16_t checksum = 0x0000; sub_cycles(ISA_CYCLES(8)); if (addr & 1) { - old = nvr->regs[local->addr]; - switch(local->addr) { + old = nvr->regs[local->addr[addr_id]]; + switch(local->addr[addr_id]) { case RTC_REGA: nvr->regs[RTC_REGA] = val; timer_load_count(nvr); @@ -559,16 +586,32 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) case RTC_REGD: /* R/O */ break; + case 0x2e: + case 0x2f: + if (local->flags & FLAG_LS_HACK) { + /* 2E and 2F are a simple sum of the values of 0E to 2D. */ + for (i = 0x0e; i < 0x2e; i++) + checksum += (uint16_t) nvr->regs[i]; + nvr->regs[0x2e] = checksum >> 8; + nvr->regs[0x2f] = checksum & 0xff; + break; + } + /*FALLTHROUGH*/ + default: /* non-RTC registers are just NVRAM */ - if (nvr->regs[local->addr] != val) { - nvr->regs[local->addr] = val; + if ((local->addr[addr_id] >= 0x38) && (local->addr[addr_id] <= 0x3f) && local->wp[0]) + break; + if ((local->addr[addr_id] >= 0xb8) && (local->addr[addr_id] <= 0xbf) && local->wp[1]) + break; + if (nvr->regs[local->addr[addr_id]] != val) { + nvr->regs[local->addr[addr_id]] = val; nvr_dosave = 1; } break; } - if ((local->addr < RTC_REGA) || ((local->cent != 0xff) && (local->addr == local->cent))) { - if ((local->addr != 1) && (local->addr != 3) && (local->addr != 5)) { + if ((local->addr[addr_id] < RTC_REGA) || ((local->cent != 0xff) && (local->addr[addr_id] == local->cent))) { + if ((local->addr[addr_id] != 1) && (local->addr[addr_id] != 3) && (local->addr[addr_id] != 5)) { if ((old != val) && !(time_sync & TIME_SYNC_ENABLED)) { /* Update internal clock. */ time_get(nvr, &tm); @@ -578,7 +621,12 @@ nvr_write(uint16_t addr, uint8_t val, void *priv) } } } else { - local->addr = (val & (nvr->size - 1)); + local->addr[addr_id] = (val & (nvr->size - 1)); + /* Some chipsets use a 256 byte NVRAM but ports 70h and 71h always access only 128 bytes. */ + if (addr_id == 0x0) + local->addr[addr_id] &= 0x7f; + else if ((addr_id == 0x1) && (local->flags & FLAG_PIIX4)) + local->addr[addr_id] = (local->addr[addr_id] & 0x7f) | 0x80; if (!(machines[machine].flags & MACHINE_MCA) && !(machines[machine].flags & MACHINE_NONMI)) nmi_mask = (~val & 0x80); @@ -593,10 +641,12 @@ nvr_read(uint16_t addr, void *priv) nvr_t *nvr = (nvr_t *)priv; local_t *local = (local_t *)nvr->data; uint8_t ret; + uint8_t addr_id = (addr & 0x0e) >> 1; + uint16_t checksum; sub_cycles(ISA_CYCLES(8)); - if (addr & 1) switch(local->addr) { + if (addr & 1) switch(local->addr[addr_id]) { case RTC_REGA: ret = (nvr->regs[RTC_REGA] & 0x7f) | local->stat; break; @@ -612,11 +662,32 @@ nvr_read(uint16_t addr, void *priv) ret = nvr->regs[RTC_REGD]; break; + case 0x2c: + if (local->flags & FLAG_LS_HACK) + ret = nvr->regs[local->addr[addr_id]] & 0x7f; + else + ret = nvr->regs[local->addr[addr_id]]; + break; + + case 0x2e: + case 0x2f: + if (local->flags & FLAG_LS_HACK) { + checksum = (nvr->regs[0x2e] << 8) | nvr->regs[0x2f]; + if (nvr->regs[0x2c] & 0x80) + checksum -= 0x80; + if (local->addr[addr_id] == 0x2e) + ret = checksum >> 8; + else + ret = checksum & 0xff; + } else + ret = nvr->regs[local->addr[addr_id]]; + break; + default: - ret = nvr->regs[local->addr]; + ret = nvr->regs[local->addr[addr_id]]; break; } else - ret = local->addr; + ret = local->addr[addr_id]; return(ret); } @@ -692,6 +763,23 @@ nvr_at_speed_changed(void *priv) } +void +nvr_at_handler(int set, uint16_t base, nvr_t *nvr) +{ + io_handler(set, base, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); +} + + +void +nvr_wp_set(int set, int h, nvr_t *nvr) +{ + local_t *local = (local_t *) nvr->data; + + local->wp[h] = set; +} + + static void * nvr_at_init(const device_t *info) { @@ -710,13 +798,20 @@ nvr_at_init(const device_t *info) /* This is machine specific. */ nvr->size = machines[machine].nvrmask + 1; local->def = 0x00; - switch(info->local) { + local->flags = 0x00; + switch(info->local & 7) { case 0: /* standard AT, no century register */ nvr->irq = 8; local->cent = 0xff; break; + case 5: /* Lucky Star LS-486E */ + local->flags |= FLAG_LS_HACK; + /*FALLTHROUGH*/ + case 1: /* standard AT */ + if (info->local == 9) + local->flags |= FLAG_PIIX4; nvr->irq = 8; local->cent = RTC_CENTURY_AT; break; @@ -738,6 +833,10 @@ nvr_at_init(const device_t *info) local->def = 0xff; break; + case 6: /* VIA VT82C586B */ + nvr->irq = 8; + local->cent = RTC_CENTURY_VIA; + break; } /* Set up any local handlers here. */ @@ -748,16 +847,24 @@ nvr_at_init(const device_t *info) /* Initialize the generic NVR. */ nvr_init(nvr); - /* Start the timers. */ - timer_add(&local->update_timer, timer_update, nvr, 0); + if (nvr_at_inited == 0) { + /* Start the timers. */ + timer_add(&local->update_timer, timer_update, nvr, 0); - timer_add(&local->rtc_timer, timer_intr, nvr, 0); - timer_load_count(nvr); - timer_set_delay_u64(&local->rtc_timer, RTCCONST); + timer_add(&local->rtc_timer, timer_intr, nvr, 0); + timer_load_count(nvr); + timer_set_delay_u64(&local->rtc_timer, RTCCONST); - /* Set up the I/O handler for this device. */ - io_sethandler(0x0070, 2, - nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + /* Set up the I/O handler for this device. */ + io_sethandler(0x0070, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + if (info->local & 8) { + io_sethandler(0x0072, 2, + nvr_read,NULL,NULL, nvr_write,NULL,NULL, nvr); + } + + nvr_at_inited = 1; + } return(nvr); } @@ -782,6 +889,9 @@ nvr_at_close(void *priv) free(nvr->data); free(nvr); + + if (nvr_at_inited == 1) + nvr_at_inited = 0; } @@ -829,3 +939,30 @@ const device_t ibmat_nvr_device = { NULL, nvr_at_speed_changed, NULL }; + +const device_t piix4_nvr_device = { + "Intel PIIX4 PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 9, + nvr_at_init, nvr_at_close, NULL, + NULL, nvr_at_speed_changed, + NULL +}; + +const device_t ls486e_nvr_device = { + "Lucky Star LS-486E PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 13, + nvr_at_init, nvr_at_close, NULL, + NULL, nvr_at_speed_changed, + NULL +}; + +const device_t via_nvr_device = { + "VIA PC/AT NVRAM", + DEVICE_ISA | DEVICE_AT, + 14, + nvr_at_init, nvr_at_close, NULL, + NULL, nvr_at_speed_changed, + NULL +}; diff --git a/src/nvr_ps2.c b/src/nvr_ps2.c index 5c943a0eb..b4074039d 100644 --- a/src/nvr_ps2.c +++ b/src/nvr_ps2.c @@ -40,9 +40,9 @@ #include #include #include "86box.h" -#include "machine/machine.h" +#include "machine.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "mem.h" #include "timer.h" #include "nvr.h" @@ -128,7 +128,8 @@ ps2_nvr_init(const device_t *info) memset(nvr->ram, 0xff, 8192); if (f != NULL) { - (void)fread(nvr->ram, 8192, 1, f); + if (fread(nvr->ram, 1, 8192, f) != 8192) + fatal("ps2_nvr_init(): Error reading EEPROM data\n"); fclose(f); } @@ -149,8 +150,6 @@ ps2_nvr_close(void *priv) fclose(f); } - free(nvr->ram); - free(nvr); } diff --git a/src/pc.c b/src/pc.c index 9f0bcc926..3c67989c0 100644 --- a/src/pc.c +++ b/src/pc.c @@ -8,15 +8,15 @@ * * Main emulator module where most things are controlled. * - * Version: @(#)pc.c 1.0.93 2019/12/05 + * Version: @(#)pc.c 1.0.94 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -26,24 +26,17 @@ #include #include #include + #define HAVE_STDARG_H #include "86box.h" #include "config.h" #include "mem.h" -#ifdef USE_NEW_DYNAREC +#include "cpu.h" #ifdef USE_DYNAREC -#include "cpu_new/cpu.h" -# include "cpu_new/codegen.h" +# include "codegen_public.h" #endif -#include "cpu_new/x86_ops.h" -#else -#include "cpu/cpu.h" -#ifdef USE_DYNAREC -# include "cpu/codegen.h" -#endif -#include "cpu/x86_ops.h" -#endif -#include "io.h" +#include "x86_ops.h" +#include "86box_io.h" #include "rom.h" #include "dma.h" #include "pci.h" @@ -54,31 +47,32 @@ #include "random.h" #include "timer.h" #include "nvr.h" -#include "machine/machine.h" +#include "machine.h" #include "bugger.h" +#include "postcard.h" #include "isamem.h" #include "isartc.h" #include "lpt.h" #include "serial.h" #include "keyboard.h" #include "mouse.h" -#include "game/gameport.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "disk/hdd.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "scsi/scsi.h" -#include "scsi/scsi_device.h" -#include "cdrom/cdrom.h" -#include "disk/zip.h" -#include "scsi/scsi_disk.h" -#include "cdrom/cdrom_image.h" -#include "network/network.h" -#include "sound/sound.h" -#include "sound/midi.h" -#include "sound/snd_speaker.h" -#include "video/video.h" +#include "gameport.h" +#include "fdd.h" +#include "fdc.h" +#include "hdd.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "scsi.h" +#include "scsi_device.h" +#include "cdrom.h" +#include "zip.h" +#include "scsi_disk.h" +#include "cdrom_image.h" +#include "network.h" +#include "sound.h" +#include "midi.h" +#include "snd_speaker.h" +#include "video.h" #include "ui.h" #include "plat.h" #include "plat_midi.h" @@ -95,6 +89,7 @@ int force_debug = 0; /* (O) force debug output */ int video_fps = RENDER_FPS; /* (O) render speed in fps */ #endif int settings_only = 0; /* (O) show only the settings dialog */ +int no_quit_confirm = 0; /* (O) do not ask for confirmation on quit */ #ifdef _WIN32 uint64_t unique_id = 0; uint64_t source_hwnd = 0; @@ -118,6 +113,7 @@ int vid_cga_contrast = 0, /* (C) video */ force_43 = 0; /* (C) video */ int serial_enabled[SERIAL_MAX] = {0,0}, /* (C) enable serial ports */ bugger_enabled = 0, /* (C) enable ISAbugger */ + postcard_enabled = 0, /* (C) enable POST card */ isamem_type[ISAMEM_MAX] = { 0,0,0,0 }, /* (C) enable ISA mem cards */ isartc_type = 0; /* (C) enable ISA RTC card */ int gfxcard = 0; /* (C) graphics/video card */ @@ -149,7 +145,7 @@ int output; int atfullspeed; int clockrate; -wchar_t exe_path[1024]; /* path (dir) of executable */ +wchar_t exe_path[2048]; /* path (dir) of executable */ wchar_t usr_path[1024]; /* path (dir) of user data */ wchar_t cfg_path[1024]; /* full path of config file */ FILE *stdlog = NULL; /* file to log output to */ @@ -323,7 +319,7 @@ pc_init(int argc, wchar_t *argv[]) uint32_t *uid, *shwnd; /* Grab the executable's full path. */ - plat_get_exe_name(exe_path, sizeof(exe_path)-1); + plat_get_exe_name(exe_path, sizeof_w(exe_path)-1); p = plat_get_filename(exe_path); *p = L'\0'; @@ -354,6 +350,7 @@ usage: printf("-L or --logfile path - set 'path' to be the logfile\n"); printf("-P or --vmpath path - set 'path' to be root for vm\n"); printf("-S or --settings - show only the settings dialog\n"); + printf("-N or --noconfirm - do not ask for confirmation on quit\n"); #ifdef _WIN32 printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n"); #endif @@ -383,6 +380,9 @@ usage: } else if (!wcscasecmp(argv[c], L"--settings") || !wcscasecmp(argv[c], L"-S")) { settings_only = 1; + } else if (!wcscasecmp(argv[c], L"--noconfirm") || + !wcscasecmp(argv[c], L"-N")) { + no_quit_confirm = 1; #ifdef _WIN32 } else if (!wcscasecmp(argv[c], L"--hwnd") || !wcscasecmp(argv[c], L"-H")) { @@ -554,8 +554,8 @@ pc_init_modules(void) /* Load the ROMs for the selected machine. */ if (! machine_available(machine)) { c = 0; + machine = -1; while (machine_get_internal_name_ex(c) != NULL) { - machine = -1; if (machine_available(c)) { ui_msgbox(MBX_INFO, (wchar_t *)IDS_2063); machine = c; @@ -767,7 +767,7 @@ pc_reset_hard_init(void) /* Reset and reconfigure the Network Card layer. */ network_reset(); - if (joystick_type != 7) + if (joystick_type != JOYSTICK_TYPE_NONE) gameport_update_joystick_type(); ui_sb_update_panes(); @@ -781,7 +781,9 @@ pc_reset_hard_init(void) /* Needs the status bar... */ if (bugger_enabled) - device_add(&bugger_device); + device_add(&bugger_device); + if (postcard_enabled) + device_add(&postcard_device); /* Reset the CPU module. */ resetx86(); diff --git a/src/pci.c b/src/pci.c index 082361c36..ada976629 100644 --- a/src/pci.c +++ b/src/pci.c @@ -25,9 +25,9 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "machine/machine.h" -#include "cpu/cpu.h" -#include "io.h" +#include "machine.h" +#include "cpu.h" +#include "86box_io.h" #include "pic.h" #include "mem.h" #include "device.h" @@ -127,7 +127,15 @@ pci_write(uint16_t port, uint8_t val, void *priv) pci_log("Writing to PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } break; @@ -150,7 +158,15 @@ pci_read(uint16_t port, void *priv) if (slot != 0xff) { if (pci_cards[slot].read) return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } return 0xff; @@ -235,10 +251,17 @@ pci_type2_write(uint16_t port, uint8_t val, void *priv) if (! pci_bus) { slot = pci_card_to_slot_mapping[pci_card]; if (slot != 0xff) { - if (pci_cards[slot].write) { + if (pci_cards[slot].write) pci_cards[slot].write(pci_func, pci_index | (port & 3), val, pci_cards[slot].priv); - } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Writing to unassigned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } } } @@ -261,10 +284,17 @@ pci_type2_read(uint16_t port, void *priv) if (! pci_bus) { slot = pci_card_to_slot_mapping[pci_card]; if (slot != 0xff) { - if (pci_cards[slot].read) { + if (pci_cards[slot].read) return pci_cards[slot].read(pci_func, pci_index | (port & 3), pci_cards[slot].priv); - } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from empty PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } +#ifdef ENABLE_PCI_LOG + else + pci_log("Reading from unasisgned PCI card on slot %02X (pci_cards[%i]) (%02X:%02X)...\n", pci_card, slot, pci_func, pci_index); +#endif } return 0xff; @@ -613,7 +643,7 @@ pci_slots_clear(void) } -static uint8_t +uint8_t trc_read(uint16_t port, void *priv) { return trc_reg & 0xfb; @@ -628,20 +658,20 @@ trc_reset(uint8_t val) cpu_alt_reset = 0; + pci_reset(); + keyboard_at_reset(); + mem_a20_alt = 0; mem_a20_recalc(); flushmmucache(); - - pci_reset(); - keyboard_at_reset(); } resetx86(); } -static void +void trc_write(uint16_t port, uint8_t val, void *priv) { pci_log("TRC Write: %02X\n", val); @@ -760,7 +790,9 @@ pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), if (((dev->type == PCI_CARD_NORMAL) && (add_type >= PCI_ADD_NORMAL)) || ((dev->type == PCI_CARD_ONBOARD) && (add_type == PCI_ADD_VIDEO)) || ((dev->type == PCI_CARD_SCSI) && (add_type == PCI_ADD_SCSI)) || - ((dev->id == add_type) && (add_type < PCI_ADD_NORMAL))) { + ((dev->type == PCI_CARD_NORTHBRIDGE) && (add_type == PCI_ADD_NORTHBRIDGE)) || + ((dev->type == PCI_CARD_SOUTHBRIDGE) && (add_type == PCI_ADD_SOUTHBRIDGE)) || + ((dev->id == add_type) && (add_type < PCI_ADD_NORTHBRIDGE))) { dev->read = read; dev->write = write; dev->priv = priv; diff --git a/src/pci.h b/src/pci.h index 18a93d9fb..473f27389 100644 --- a/src/pci.h +++ b/src/pci.h @@ -46,16 +46,21 @@ #define PCI_IRQ_DISABLED -1 enum { - PCI_CARD_NORMAL = 0, + PCI_CARD_NORTHBRIDGE = 0, + PCI_CARD_SOUTHBRIDGE, + PCI_CARD_NORMAL, PCI_CARD_ONBOARD, PCI_CARD_SCSI, PCI_CARD_SPECIAL }; - -#define PCI_ADD_NORMAL 0x80 -#define PCI_ADD_VIDEO 0x81 -#define PCI_ADD_SCSI 0x82 +enum { + PCI_ADD_NORTHBRIDGE = 0x80, + PCI_ADD_SOUTHBRIDGE, + PCI_ADD_NORMAL, + PCI_ADD_VIDEO, + PCI_ADD_SCSI +}; typedef union { uint32_t addr; @@ -90,6 +95,10 @@ extern void pci_close(void); extern uint8_t pci_add_card(uint8_t add_type, uint8_t (*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv); extern void trc_init(void); + +extern uint8_t trc_read(uint16_t port, void *priv); +extern void trc_write(uint16_t port, uint8_t val, void *priv); + extern void pci_elcr_set_enabled(int enabled); diff --git a/src/pci_dummy.c b/src/pci_dummy.c index 6a790ff14..02819618b 100644 --- a/src/pci_dummy.c +++ b/src/pci_dummy.c @@ -4,7 +4,7 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "pci.h" #include "pci_dummy.h" diff --git a/src/pic.c b/src/pic.c index 60297734c..ad8cc00d5 100644 --- a/src/pic.c +++ b/src/pic.c @@ -8,11 +8,11 @@ * * Implementation of the Intel PIC chip emulation. * - * Version: @(#)pic.c 1.0.5 2019/09/20 + * Version: @(#)pic.c 1.0.7 2020/01/21 * * Author: Miran Grca, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -21,21 +21,24 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "cpu/cpu.h" -#include "machine/machine.h" -#include "io.h" +#include "cpu.h" +#include "machine.h" +#include "86box_io.h" #include "pci.h" #include "pic.h" #include "timer.h" #include "pit.h" -int output; -int intclear; -int keywaiting=0; -int pic_intpending; -PIC pic, pic2; -uint16_t pic_current; +int output; +int intclear; +int keywaiting = 0; +int pic_intpending; +PIC pic, pic2; +uint16_t pic_current; + + +static int shadow = 0; #ifdef ENABLE_PIC_LOG @@ -98,6 +101,13 @@ pic_reset() } +void +pic_set_shadow(int sh) +{ + shadow = sh; +} + + void pic_update_mask(uint8_t *mask, uint8_t ins) { @@ -198,6 +208,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv) pic_updatepending(); } else if (!(val & 8)) { /*OCW2*/ + pic.ocw2 = val; if ((val & 0xE0) == 0x60) { pic.ins &= ~(1 << (val & 7)); pic_update_mask(&pic.mask2, pic.ins); @@ -226,6 +237,7 @@ pic_write(uint16_t addr, uint8_t val, void *priv) } } } else { /*OCW3*/ + pic.ocw3 = val; if (val & 2) pic.read=(val & 1); } @@ -236,27 +248,36 @@ pic_write(uint16_t addr, uint8_t val, void *priv) uint8_t pic_read(uint16_t addr, void *priv) { - addr &= ~0x06; + uint8_t ret = 0xff; - if (addr & 1) { - pic_log("Read PIC mask %02X\n", pic.mask); - pic_log("%04X:%04X: Read PIC mask %02X\n", CS, cpu_state.pc, pic.mask); - return pic.mask; - } - if (pic.read) { - pic_log("Read PIC ins %02X\n", pic.ins); + if ((addr == 0x20) && shadow) { + ret = ((pic.ocw3 & 0x20) >> 5) << 4; + ret |= ((pic.ocw2 & 0x80) >> 7) << 3; + ret |= ((pic.icw4 & 0x10) >> 4) << 2; + ret |= ((pic.icw4 & 0x02) >> 1) << 1; + ret |= ((pic.icw4 & 0x08) >> 3) << 0; + } else if ((addr == 0x21) && shadow) + ret = ((pic.vector & 0xf8) >> 3) << 0; + else if (addr & 1) + ret = pic.mask; + else if (pic.read) { if (AT) - return pic.ins | (pic2.ins ? 4 : 0); + ret = pic.ins | (pic2.ins ? 4 : 0); else - return pic.ins; - } - return pic.pend; + ret = pic.ins; + } else + ret = pic.pend; + + pic_log("%04X:%04X: Read PIC 1 port %04X, value %02X\n", CS, cpu_state.pc, addr, val); + + return ret; } void pic_init() { + shadow = 0; io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL); } @@ -264,6 +285,7 @@ pic_init() void pic_init_pcjr() { + shadow = 0; io_sethandler(0x0020, 0x0008, pic_read, NULL, NULL, pic_write, NULL, NULL, NULL); } @@ -323,6 +345,36 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) pic.pend &= ~4; pic_updatepending(); } else if (!(val & 8)) { /*OCW2*/ +#ifdef ENABLE_PIC_LOG + switch ((val >> 5) & 0x07) { + case 0x00: + pic_log("Rotate in automatic EOI mode (clear)\n"); + break; + case 0x01: + pic_log("Non-specific EOI command\n"); + break; + case 0x02: + pic_log("No operation\n"); + break; + case 0x03: + pic_log("Specific EOI command\n"); + break; + case 0x04: + pic_log("Rotate in automatic EOI mode (set)\n"); + break; + case 0x05: + pic_log("Rotate on on-specific EOI command\n"); + break; + case 0x06: + pic_log("Set priority command\n"); + break; + case 0x07: + pic_log("Rotate on specific EOI command\n"); + break; + } +#endif + + pic2.ocw2 = val; if ((val & 0xE0) == 0x60) { pic2.ins &= ~(1 << (val & 7)); pic_update_mask(&pic2.mask2, pic2.ins); @@ -339,6 +391,7 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) } } } else { /*OCW3*/ + pic2.ocw3 = val; if (val & 2) pic2.read=(val & 1); } @@ -349,16 +402,26 @@ pic2_write(uint16_t addr, uint8_t val, void *priv) uint8_t pic2_read(uint16_t addr, void *priv) { - if (addr&1) { - pic_log("Read PIC2 mask %02X\n", pic2.mask); - return pic2.mask; - } - if (pic2.read) { - pic_log("Read PIC2 ins %02X\n", pic2.ins); - return pic2.ins; - } - pic_log("Read PIC2 pend %02X\n", pic2.pend); - return pic2.pend; + uint8_t ret = 0xff; + + if ((addr == 0xa0) && shadow) { + ret = ((pic2.ocw3 & 0x20) >> 5) << 4; + ret |= ((pic2.ocw2 & 0x80) >> 7) << 3; + ret |= ((pic2.icw4 & 0x10) >> 4) << 2; + ret |= ((pic2.icw4 & 0x02) >> 1) << 1; + ret |= ((pic2.icw4 & 0x08) >> 3) << 0; + } else if ((addr == 0xa1) && shadow) + ret = ((pic2.vector & 0xf8) >> 3) << 0; + else if (addr & 1) + ret = pic2.mask; + else if (pic2.read) + ret = pic2.ins; + else + ret = pic2.pend; + + pic_log("%04X:%04X: Read PIC 2 port %04X, value %02X\n", CS, cpu_state.pc, addr, val); + + return ret; } @@ -478,21 +541,32 @@ pic_process_interrupt(PIC* target_pic, int c) { uint8_t pending = target_pic->pend & ~target_pic->mask; int ret = -1; + /* TODO: On init, a PIC need to get a pointer to one of these, and rotate as needed + if in rotate mode. */ + /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 */ + int priority_xt[16] = { 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1 }; + int priority_at[16] = { 14, 13, -1, 4, 3, 2, 1, 0, 12, 11, 10, 9, 8, 7, 6, 5 }; + int i; int pic_int = c & 7; int pic_int_num = 1 << pic_int; int in_service = 0; - in_service = (target_pic->ins & (pic_int_num - 1)); /* Is anything of higher priority already in service? */ - in_service |= (target_pic->ins & pic_int_num); /* Is the current IRQ already in service? */ if (AT) { - /* AT-specific stuff. */ - if (c >= 8) - in_service |= (pic.ins & 0x03); /* IRQ 8 to 15, are IRQ's with higher priorities than the - cascade IRQ already in service? */ - /* For IRQ 0 to 7, the cascade IRQ's in service bit indicates that one or - more IRQ's between 8 and 15 are already in service. */ + for (i = 0; i < 16; i++) { + if ((priority_at[i] != -1) && (priority_at[i] >= priority_at[c])) { + if (i < 8) + in_service |= (pic.ins & (1 << i)); + else + in_service |= (pic2.ins & (1 << i)); + } + } + } else { + for (i = 0; i < 16; i++) { + if ((priority_xt[i] != -1) && (priority_xt[i] >= priority_xt[c])) + in_service |= (pic.ins & (1 << i)); + } } if ((pending & pic_int_num) && !in_service) { diff --git a/src/pic.h b/src/pic.h index c164a0aa9..10684958a 100644 --- a/src/pic.h +++ b/src/pic.h @@ -3,10 +3,8 @@ typedef struct PIC { - uint8_t icw1,icw3,icw4,mask,ins,pend,mask2; - int icw; - uint8_t vector; - int read; + uint8_t icw1, icw3, icw4, mask, ins, pend, mask2, vector, ocw2, ocw3; + int icw, read; } PIC; @@ -14,6 +12,7 @@ extern PIC pic, pic2; extern int pic_intpending; +extern void pic_set_shadow(int sh); extern void pic_init(void); extern void pic_init_pcjr(void); extern void pic2_init(void); diff --git a/src/piix.h b/src/piix.h index 6de1d65b3..2987cef7e 100644 --- a/src/piix.h +++ b/src/piix.h @@ -8,14 +8,15 @@ * * Emulation core dispatcher. * - * Version: @(#)piix.h 1.0.3 2018/05/11 + * Version: @(#)piix.h 1.0.4 2020/01/24 * * Authors: Sarah Walker, * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ extern const device_t piix_device; -extern const device_t piix_pb640_device; extern const device_t piix3_device; +extern const device_t piix4_device; +extern const device_t piix4e_device; diff --git a/src/pit.c b/src/pit.c index 3fe4fb1dd..f3421a8f4 100644 --- a/src/pit.c +++ b/src/pit.c @@ -24,11 +24,11 @@ #include #define HAVE_STDARG_H #include "86box.h" -#include "cpu/cpu.h" +#include "cpu.h" #include "device.h" #include "timer.h" #include "dma.h" -#include "io.h" +#include "86box_io.h" #include "nmi.h" #include "pic.h" #include "timer.h" @@ -43,7 +43,8 @@ pit_t *pit, *pit2; double cpuclock, PITCONSTD, SYSCLK, - isa_timing, bus_timing; + isa_timing, + bus_timing, pci_timing; uint64_t PITCONST, ISACONST, CGACONST, @@ -57,8 +58,9 @@ int io_delay = 5; int64_t firsttime = 1; -#define PIT_PS2 16 -#define PIT_EXT_IO 32 +#define PIT_PS2 16 /* The PIT is the PS/2's second PIT. */ +#define PIT_EXT_IO 32 /* The PIT has externally specified port I/O. */ +#define PIT_CUSTOM_CLOCK 64 /* The PIT uses custom clock inputs provided by another provider. */ enum { @@ -99,6 +101,55 @@ ctr_set_out(ctr_t *ctr, int out) } +static void +ctr_decrease_count(ctr_t *ctr) +{ + uint8_t units, tens, hundreds, thousands, myriads; + int dec_cnt = 1; + + if (ctr->ctrl & 0x01) { + units = ctr->count & 0x0f; + tens = (ctr->count >> 4) & 0x0f; + hundreds = (ctr->count >> 8) & 0x0f; + thousands = (ctr->count >> 12) & 0x0f; + myriads = (ctr->count >> 16) & 0x0f; + + dec_cnt -= units; + units = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; /* The +9 is so we get a carry if dec_cnt % 10 was not a 0. */ + if (dec_cnt <= tens) + tens -= dec_cnt; + else { + dec_cnt -= tens; + tens = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + if (dec_cnt <= hundreds) + hundreds -= dec_cnt; + else { + dec_cnt -= hundreds; + hundreds = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + if (dec_cnt <= thousands) + thousands -= dec_cnt; + else { + dec_cnt -= thousands; + thousands = (10 - dec_cnt % 10) % 10; + + dec_cnt = (dec_cnt + 9) / 10; + myriads = (10 + myriads - dec_cnt % 10) % 10; + } + } + } + + ctr->count = (myriads << 16) | (thousands << 12) | (hundreds << 8) | (tens << 4) | units; + } else + ctr->count = (ctr->count - 1) & 0xffff; +} + + static void ctr_load_count(ctr_t *ctr) { @@ -124,7 +175,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->gate && (ctr->count >= 1)) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 1); @@ -132,7 +183,7 @@ ctr_tick(ctr_t *ctr) } break; case 3: - ctr->count = (ctr->count - 1) & 0xffff; + ctr_decrease_count(ctr); break; } break; @@ -146,7 +197,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->count >= 1) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 1); @@ -154,7 +205,7 @@ ctr_tick(ctr_t *ctr) } break; case 3: - ctr->count = (ctr->count - 1) & 0xffff; + ctr_decrease_count(ctr); break; } break; @@ -171,7 +222,7 @@ ctr_tick(ctr_t *ctr) if (ctr->gate == 0) break; else if (ctr->count >= 2) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 2) { ctr->state = 3; ctr_set_out(ctr, 0); @@ -221,7 +272,7 @@ ctr_tick(ctr_t *ctr) if ((ctr->gate != 0) || (ctr->m != 4)) { switch(ctr->state) { case 0: - ctr->count--; + ctr_decrease_count(ctr); break; case 1: ctr_load_count(ctr); @@ -229,7 +280,7 @@ ctr_tick(ctr_t *ctr) break; case 2: if (ctr->count >= 1) { - ctr->count--; + ctr_decrease_count(ctr); if (ctr->count < 1) { ctr->state = 3; ctr_set_out(ctr, 0); @@ -406,6 +457,38 @@ pit_ctr_set_gate(ctr_t *ctr, int gate) } +void +pit_ctr_set_clock(ctr_t *ctr, int clock) +{ + int old = ctr->clock; + + ctr->clock = clock; + + if (ctr->using_timer && ctr->latch) { + if (old && !ctr->clock) { + ctr_set_state_1(ctr); + ctr->latch = 0; + } + } else if (ctr->using_timer && !ctr->latch) { + if (ctr->state == 1) { + if (!old && ctr->clock) + ctr->s1_det = 1; /* Rising edge. */ + else if (old && !ctr->clock) { + ctr->s1_det++; /* Falling edge. */ + if (ctr->s1_det != 2) + ctr->s1_det = 0; + } + + if (ctr->s1_det == 2) { + ctr->s1_det = 0; + ctr_tick(ctr); + } + } else if (old && !ctr->clock) + ctr_tick(ctr); + } +} + + void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer) { @@ -420,38 +503,11 @@ pit_timer_over(void *p) { pit_t *dev = (pit_t *) p; int i; - ctr_t *ctr; - int old; - old = dev->clock; dev->clock ^= 1; - for (i = 0; i < 3; i++) { - ctr = &dev->counters[i]; - - if (ctr->using_timer && ctr->latch) { - if (old && !dev->clock) { - ctr_set_state_1(ctr); - ctr->latch = 0; - } - } else if (ctr->using_timer && !ctr->latch) { - if (ctr->state == 1) { - if (!old && dev->clock) - ctr->s1_det = 1; /* Rising edge. */ - else if (old && !dev->clock) { - ctr->s1_det++; /* Falling edge. */ - if (ctr->s1_det != 2) - ctr->s1_det = 0; - } - - if (ctr->s1_det == 2) { - ctr->s1_det = 0; - ctr_tick(ctr); - } - } else if (old && !dev->clock) - ctr_tick(ctr); - } - } + for (i = 0; i < 3; i++) + pit_ctr_set_clock(&dev->counters[i], dev->clock); timer_advance_u64(&dev->callback_timer, PITCONST >> 1ULL); } @@ -780,7 +836,7 @@ pit_init(const device_t *info) pit_t *dev = (pit_t *) malloc(sizeof(pit_t)); pit_reset(dev); - if (!(dev->flags & PIT_PS2)) { + if (!(dev->flags & PIT_PS2) && !(dev->flags & PIT_CUSTOM_CLOCK)) { timer_add(&dev->callback_timer, pit_timer_over, (void *) dev, 0); timer_set_delay_u64(&dev->callback_timer, PITCONST >> 1ULL); } @@ -969,7 +1025,9 @@ pit_set_clock(int clock) TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32)); isa_timing = (cpuclock / (double)8000000.0); + bus_timing = (cpuclock / (double)cpu_busspeed); + pci_timing = (cpuclock / (double)cpu_pci_speed); if (cpu_busspeed >= 30000000) SYSCLK = bus_timing * 4.0; diff --git a/src/pit.h b/src/pit.h index e0a4a42ff..f019327a6 100644 --- a/src/pit.h +++ b/src/pit.h @@ -9,10 +9,10 @@ * Header of the implementation of the Intel 8253/8254 * Programmable Interval Timer. * - * Version: @(#)pit.h 1.0.0 2019/12/02 + * Version: @(#)pit.h 1.0.1 2020/01/17 * * Author: Miran Grca, - * Copyright 2019 Miran Grca. + * Copyright 2019,2020 Miran Grca. */ #ifndef EMU_PIT_H # define EMU_PIT_H @@ -27,7 +27,7 @@ typedef struct { int rm, wm, gate, out, newcount, count, using_timer, latched, - state, null_count, do_read_status, pad1; + state, null_count, do_read_status, clock; uint32_t l; @@ -60,10 +60,17 @@ extern uint64_t PITCONST, ISACONST, RTCCONST; +/* Gets a counter's count. */ extern uint16_t pit_ctr_get_count(ctr_t *ctr); +/* Sets a counter's load count handler. */ extern void pit_ctr_set_load_func(ctr_t *ctr, void (*func)(uint8_t new_m, int new_count)); +/* Sets a counter's OUT output handler. */ extern void pit_ctr_set_out_func(ctr_t *ctr, void (*func)(int new_out, int old_out)); +/* Sets a counter's GATE input. */ extern void pit_ctr_set_gate(ctr_t *ctr, int gate); +/* Sets a counter's CLOCK input. */ +extern void pit_ctr_set_clock(ctr_t *ctr, int clock); +/* Sets if a counter's CLOCK input is from the timer or not - used by PCjr. */ extern void pit_ctr_set_using_timer(ctr_t *ctr, int using_timer); extern pit_t * pit_common_init(int type, void (*out0)(int new_out, int old_out), void (*out1)(int new_out, int old_out)); diff --git a/src/plat.h b/src/plat.h index 065d50aa0..ec5391bae 100644 --- a/src/plat.h +++ b/src/plat.h @@ -58,7 +58,7 @@ GLOBAL int dopause, /* system is paused */ mouse_capture; /* mouse is captured in app */ GLOBAL uint64_t timer_freq; GLOBAL int infocus; -GLOBAL char emu_version[128]; /* version ID string */ +GLOBAL char emu_version[200]; /* version ID string */ GLOBAL int rctrl_is_lalt; GLOBAL int update_icons; diff --git a/src/port_92.c b/src/port_92.c index 1c5f1b2bf..7230111f2 100644 --- a/src/port_92.c +++ b/src/port_92.c @@ -22,13 +22,9 @@ #include #include "86box.h" #include "device.h" -#ifdef USE_NEW_DYNAREC -#include "cpu_new/cpu.h" -#else -#include "cpu/cpu.h" -#endif +#include "cpu.h" #include "timer.h" -#include "io.h" +#include "86box_io.h" #include "keyboard.h" #include "mem.h" #include "pit.h" diff --git a/src/postcard.c b/src/postcard.c new file mode 100644 index 000000000..9662d3ae6 --- /dev/null +++ b/src/postcard.c @@ -0,0 +1,142 @@ +/* + * 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 a port 80h POST diagnostic card. + * + * Version: @(#)postcard.c 1.0.0 2020/03/23 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "86box_io.h" +#include "device.h" +#include "machine.h" +#include "plat.h" +#include "ui.h" +#include "postcard.h" + + +static uint16_t postcard_port; +static uint8_t postcard_written; +static uint8_t postcard_code, postcard_prev_code; +#define UISTR_LEN 13 +static char postcard_str[UISTR_LEN]; /* UI output string */ + + +extern void ui_sb_bugui(char *__str); + + +#ifdef ENABLE_POSTCARD_LOG +int postcard_do_log = ENABLE_POSTCARD_LOG; + + +static void +postcard_log(const char *fmt, ...) +{ + va_list ap; + + if (postcard_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +int postcard_do_log = 0; + +#define postcard_log(fmt, ...) +#endif + + +static void +postcard_setui(void) +{ + if (!postcard_written) + sprintf(postcard_str, "POST: -- --"); + else if (postcard_written == 1) + sprintf(postcard_str, "POST: %02X --", postcard_code); + else + sprintf(postcard_str, "POST: %02X %02X", postcard_code, postcard_prev_code); + + ui_sb_bugui(postcard_str); + + if (postcard_do_log) { + /* log same string sent to the UI */ + int len = strlen(postcard_str); + postcard_str[len + 1] = '\0'; + postcard_str[len] = '\n'; + postcard_log(postcard_str); + } +} + + +static void +postcard_reset(void) +{ + postcard_written = 0; + postcard_code = postcard_prev_code = 0x00; + + postcard_setui(); +} + + +static void +postcard_write(uint16_t port, uint8_t val, void *priv) +{ + postcard_prev_code = postcard_code; + postcard_code = val; + if (postcard_written < 2) + postcard_written++; + + postcard_setui(); +} + + +static void * +postcard_init(const device_t *info) +{ + postcard_reset(); + + if (machines[machine].flags & MACHINE_MCA) + postcard_port = 0x680; /* MCA machines */ + else if (strstr(machines[machine].name, " PS/2 ")) + postcard_port = 0x90; /* ISA PS/2 machines */ + else + postcard_port = 0x80; /* AT and clone machines */ + postcard_log("POST card initializing on port %04Xh\n", postcard_port); + + if (postcard_port) io_sethandler(postcard_port, 1, + NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); + + return postcard_write; +} + + +static void +postcard_close(UNUSED(void *priv)) +{ + if (postcard_port) io_removehandler(postcard_port, 1, + NULL, NULL, NULL, postcard_write, NULL, NULL, NULL); +} + + +const device_t postcard_device = { + "POST Card", + DEVICE_ISA, + 0, + postcard_init, postcard_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/postcard.h b/src/postcard.h new file mode 100644 index 000000000..4bfc912f5 --- /dev/null +++ b/src/postcard.h @@ -0,0 +1,35 @@ +/* + * 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 a port 80h POST diagnostic card. + * + * Version: @(#)postcard.c 1.0.0 2020/03/23 + * + * Author: RichardG, + * Copyright 2020 RichardG. + */ +#ifndef POSTCARD_H +# define POSTCARD_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Global variables. */ +extern const device_t postcard_device; + + +/* Functions. */ + +#ifdef __cplusplus +} +#endif + + +#endif /*BUGGER_H*/ diff --git a/src/printer/png.c b/src/printer/png.c index 752df0080..7d4555bd2 100644 --- a/src/printer/png.c +++ b/src/printer/png.c @@ -52,11 +52,11 @@ #include #define PNG_DEBUG 0 #include -#include "../86box.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../ui.h" -#include "../video/video.h" +#include "86box.h" +#include "plat.h" +#include "plat_dynld.h" +#include "ui.h" +#include "video.h" #include "png_struct.h" #ifdef _WIN32 diff --git a/src/printer/prt_cpmap.c b/src/printer/prt_cpmap.c index f7c7330f6..8713d0809 100644 --- a/src/printer/prt_cpmap.c +++ b/src/printer/prt_cpmap.c @@ -53,8 +53,8 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" +#include "86box.h" +#include "plat.h" #include "printer.h" diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index 597105cd4..c965285ab 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -10,12 +10,12 @@ * * Version: @(#)prt_escp.c 1.0.7 2019/09/23 * - * Authors: Michael Drüing, + * Authors: Michael Dr�ing, * Fred N. van Kempen, * * Based on code by Frederic Weymann (originally for DosBox.) * - * Copyright 2018,2019 Michael Drüing. + * Copyright 2018,2019 Michael Dr�ing. * Copyright 2019,2019 Fred N. van Kempen. * * Redistribution and use in source and binary forms, with @@ -56,18 +56,18 @@ #include #include #include FT_FREETYPE_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../pit.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../ui.h" -#include "../lpt.h" -#include "../video/video.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "pit.h" +#include "plat.h" +#include "plat_dynld.h" +#include "ui.h" +#include "lpt.h" +#include "video.h" #include "png_struct.h" #include "printer.h" #include "prt_devs.h" @@ -228,7 +228,7 @@ typedef struct { double horizontal_tabs[32]; uint8_t num_horizontal_tabs; double vertical_tabs[16]; - uint8_t num_vertical_tabs; + int8_t num_vertical_tabs; /* bit graphics data */ uint16_t bg_h_density; /* in dpi */ @@ -410,15 +410,17 @@ static void new_page(escp_t *dev, int8_t save, int8_t resetx) { /* Dump the current page if needed. */ - if (save) + if (save && dev->page) dump_page(dev); if (resetx) dev->curr_x = dev->left_margin; /* Clear page. */ dev->curr_y = dev->top_margin; - dev->page->dirty = 0; - memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + if (dev->page) { + dev->page->dirty = 0; + memset(dev->page->pixels, 0x00, dev->page->pitch * dev->page->h); + } /* Make the page's file name. */ plat_tempfile(dev->page_fn, NULL, L".png"); @@ -2056,6 +2058,11 @@ escp_init(void *lpt) dev->lpt = lpt; /* Create a full pathname for the font files. */ + if(wcslen(exe_path) >= sizeof_w(dev->fontpath)) { + free(dev); + return(NULL); + } + wcscpy(dev->fontpath, exe_path); plat_path_slash(dev->fontpath); wcscat(dev->fontpath, L"roms/printer/fonts/"); diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index effb2d07e..22d5f85b8 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -22,14 +22,14 @@ #include #include #include -#include "../86box.h" -#include "../lang/language.h" -#include "../lpt.h" -#include "../timer.h" -#include "../pit.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../ui.h" +#include "86box.h" +#include "language.h" +#include "lpt.h" +#include "timer.h" +#include "pit.h" +#include "plat.h" +#include "plat_dynld.h" +#include "ui.h" #include "prt_devs.h" #if defined(_WIN32) && !defined(__WINDOWS__) @@ -86,7 +86,7 @@ typedef struct wchar_t filename[260]; char buffer[POSTSCRIPT_BUFFER_LENGTH]; - uint16_t buffer_pos; + size_t buffer_pos; } ps_t; static void @@ -271,13 +271,13 @@ static void process_data(ps_t *dev) { if (dev->data < 0x20 || dev->data == 0x7F) { - if (process_nonprintable(dev)) { + if (process_nonprintable(dev)) return; - } } if (dev->buffer_pos == POSTSCRIPT_BUFFER_LENGTH) { write_buffer(dev, false); + dev->buffer_pos = 0; } dev->buffer[dev->buffer_pos++] = dev->data; diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index aa56ae2e1..9219221f1 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -56,12 +56,12 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../pit.h" -#include "../plat.h" -#include "../lpt.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "pit.h" +#include "plat.h" +#include "lpt.h" #include "printer.h" #include "prt_devs.h" @@ -465,13 +465,14 @@ prnt_close(void *priv) { prnt_t *dev = (prnt_t *)priv; - if (dev == NULL) return; + if (dev == NULL) + return; - /* print last page if it contains data */ - if (dev->page->dirty) - dump_page(dev); + if (dev->page) { + /* print last page if it contains data */ + if (dev->page->dirty) + dump_page(dev); - if (dev->page != NULL) { if (dev->page->chars != NULL) free(dev->page->chars); free(dev->page); diff --git a/src/rom.c b/src/rom.c index 204fd0eee..1853fb3f0 100644 --- a/src/rom.c +++ b/src/rom.c @@ -33,8 +33,8 @@ #include "mem.h" #include "rom.h" #include "plat.h" -#include "machine/machine.h" -#include "machine/m_xt_xi8088.h" +#include "machine.h" +#include "m_xt_xi8088.h" #ifdef ENABLE_ROM_LOG @@ -62,7 +62,10 @@ rom_fopen(wchar_t *fn, wchar_t *mode) { wchar_t temp[1024]; - wcscpy(temp, exe_path); + if (wcslen(exe_path) <= 1024) + wcscpy(temp, exe_path); + else + wcsncpy(temp, exe_path, 1024); plat_put_backslash(temp); wcscat(temp, fn); @@ -118,7 +121,7 @@ rom_read(uint32_t addr, void *priv) return 0xff; if (addr >= (rom->mapping.base + rom->sz)) return 0xff; - return(rom->rom[addr & rom->mask]); + return(rom->rom[(addr - rom->mapping.base) & rom->mask]); } @@ -136,7 +139,7 @@ rom_readw(uint32_t addr, void *priv) return 0xffff; if (addr >= (rom->mapping.base + rom->sz)) return 0xffff; - return(*(uint16_t *)&rom->rom[addr & rom->mask]); + return(*(uint16_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); } @@ -154,7 +157,7 @@ rom_readl(uint32_t addr, void *priv) return 0xffffffff; if (addr >= (rom->mapping.base + rom->sz)) return 0xffffffff; - return(*(uint32_t *)&rom->rom[addr & rom->mask]); + return(*(uint32_t *)&rom->rom[(addr - rom->mapping.base) & rom->mask]); } @@ -171,17 +174,15 @@ rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr) /* Make sure we only look at the base-256K offset. */ if (addr >= 0x40000) - { addr = 0; - } else - { addr &= 0x03ffff; - } if (ptr != NULL) { - (void)fseek(f, off, SEEK_SET); - (void)fread(ptr+addr, sz, 1, f); + if (fseek(f, off, SEEK_SET) == -1) + fatal("rom_load_linear(): Error seeking to the beginning of the file\n"); + if (fread(ptr+addr, 1, sz, f) > sz) + fatal("rom_load_linear(): Error reading data\n"); } (void)fclose(f); @@ -218,9 +219,12 @@ rom_load_linear_inverted(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *p } if (ptr != NULL) { - (void)fseek(f, off, SEEK_SET); - (void)fread(ptr+addr+0x10000, sz >> 1, 1, f); - (void)fread(ptr+addr, sz >> 1, 1, f); + if (fseek(f, off, SEEK_SET) == -1) + fatal("rom_load_linear_inverted(): Error seeking to the beginning of the file\n"); + if (fread(ptr+addr+0x10000, 1, sz >> 1, f) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the upper half of the data\n"); + if (fread(ptr+addr, sz >> 1, 1, f) > (sz >> 1)) + fatal("rom_load_linear_inverted(): Error reading the lower half of the data\n"); } (void)fclose(f); @@ -260,8 +264,8 @@ rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int off, (void)fseek(fl, off, SEEK_SET); (void)fseek(fh, off, SEEK_SET); for (c=0; c #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../disk/hdc.h" -#include "../disk/hdd.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "hdc.h" +#include "hdd.h" +#include "plat.h" #include "scsi.h" #include "scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" +#include "cdrom.h" +#include "zip.h" #include "scsi_disk.h" #include "scsi_aha154x.h" #include "scsi_buslogic.h" #include "scsi_ncr5380.h" #include "scsi_ncr53c8xx.h" +#include "scsi_spock.h" #ifdef WALTJE # include "scsi_wd33c93.h" #endif @@ -60,7 +61,7 @@ static SCSI_CARD scsi_cards[] = { { "[ISA] Adaptec AHA-154xB", "aha154xb", &aha154xb_device, }, { "[ISA] Adaptec AHA-154xC", "aha154xc", &aha154xc_device, }, { "[ISA] Adaptec AHA-154xCF", "aha154xcf", &aha154xcf_device, }, - { "[ISA] BusLogic BT-542B", "bt542b", &buslogic_542b_1991_device, }, + { "[ISA] BusLogic BT-542B", "bt542b", &buslogic_542b_1991_device, }, { "[ISA] BusLogic BT-542BH", "bt542bh", &buslogic_device, }, { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device, }, { "[ISA] Longshine LCS-6821N", "lcs6821n", &scsi_lcs6821n_device, }, @@ -72,9 +73,11 @@ static SCSI_CARD scsi_cards[] = { #endif { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, }, { "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device, }, + { "[MCA] IBM PS/2 SCSI", "spock", &spock_device, }, { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, }, { "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device, }, - //{ "[PCI] NCR 53C825A", "ncr53c825a", &ncr53c825a_pci_device, }, + { "[PCI] NCR 53C825A", "ncr53c825a", &ncr53c825a_pci_device, }, + { "[PCI] NCR 53C860", "ncr53c860", &ncr53c860_pci_device, }, { "[PCI] NCR 53C875", "ncr53c875", &ncr53c875_pci_device, }, { "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device, }, { "", "", NULL, }, diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index a33d35f07..b3ec5f4a9 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -24,19 +24,18 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mca.h" -#include "../mem.h" -#include "../mca.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../dma.h" -#include "../pic.h" -#include "../plat.h" -// #include "../cpu/cpu.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mca.h" +#include "mem.h" +#include "mca.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "dma.h" +#include "pic.h" +#include "plat.h" #include "scsi.h" #include "scsi_aha154x.h" #include "scsi_x54x.h" @@ -729,7 +728,8 @@ aha_setnvr(x54x_t *dev) f = nvr_fopen(dev->nvr_path, L"rb"); if (f) { - fread(dev->nvr, 1, NVR_SIZE, f); + if (fread(dev->nvr, 1, NVR_SIZE, f) != NVR_SIZE) + fatal("aha_setnvr(): Error reading data\n"); fclose(f); f = NULL; } else diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 15a4dc7d4..48d19c9f5 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -27,19 +27,19 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mca.h" -#include "../mem.h" -#include "../mca.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../dma.h" -#include "../pic.h" -#include "../pci.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mca.h" +#include "mem.h" +#include "mca.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "dma.h" +#include "pic.h" +#include "pci.h" +#include "plat.h" #include "scsi.h" #include "scsi_buslogic.h" #include "scsi_device.h" @@ -410,7 +410,8 @@ BuslogicInitializeAutoSCSIRam(x54x_t *dev) f = nvr_fopen(BuslogicGetNVRFileName(bl), L"rb"); if (f) { - fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); + if (fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f) != 64) + fatal("BuslogicInitializeAutoSCSIRam(): Error reading data\n"); fclose(f); f = NULL; if (bl->chip == CHIP_BUSLOGIC_PCI) { @@ -624,10 +625,6 @@ BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, u buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); - if (ESCSICmd->DataDirection > 0x03) { - buslogic_log("Invalid control byte: %02X\n", - ESCSICmd->DataDirection); - } } target_cdb_len = 12; @@ -1229,6 +1226,7 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) case 0x10: val &= 0xe0; val |= 1; + /*FALLTHROUGH*/ case 0x11: case 0x12: case 0x13: /* I/O Base set. */ @@ -1250,6 +1248,7 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) case 0x14: val &= 0xe0; + /*FALLTHROUGH*/ case 0x15: case 0x16: case 0x17: /* MMIO Base set. */ diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index abfd8a6ef..6527340f9 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -9,11 +9,11 @@ * Implementation of the CD-ROM drive with SCSI(-like) * commands, for both ATAPI and SCSI usage. * - * Version: @(#)scsi_cdrom.c 1.0.73 2019/12/13 + * Version: @(#)scsi_cdrom.c 1.0.75 2020/03/23 * * Author: Miran Grca, * - * Copyright 2016-2019 Miran Grca. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -23,19 +23,19 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../config.h" -#include "../timer.h" -#include "../device.h" -#include "../piix.h" -#include "../scsi/scsi_device.h" -#include "../nvr.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../sound/sound.h" -#include "../plat.h" -#include "../ui.h" -#include "../cdrom/cdrom.h" +#include "86box.h" +#include "config.h" +#include "timer.h" +#include "device.h" +#include "piix.h" +#include "scsi_device.h" +#include "nvr.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "sound.h" +#include "plat.h" +#include "ui.h" +#include "cdrom.h" #include "scsi_cdrom.h" @@ -139,9 +139,15 @@ const uint8_t scsi_cdrom_command_flags[0x100] = IMPLEMENTED, /* 0xBD */ IMPLEMENTED | CHECK_READY, /* 0xBE */ IMPLEMENTED | CHECK_READY, /* 0xBF */ - 0, 0, /* 0xC0-0xC1 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC0 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC1 */ IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC2 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC3-0xCC */ + 0, /* 0xC3 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC4 */ + 0, /* 0xC5 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC6 */ + IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xC7 */ + 0, 0, 0, 0, 0, /* 0xC8-0xCC */ IMPLEMENTED | CHECK_READY | SCSI_ONLY, /* 0xCD */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xCE-0xD9 */ IMPLEMENTED | SCSI_ONLY, /* 0xDA */ @@ -151,6 +157,7 @@ const uint8_t scsi_cdrom_command_flags[0x100] = }; static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | + GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | GPMODEP_CAPABILITIES_PAGE | @@ -207,7 +214,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, - { 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -254,7 +261,7 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { { { 0, 0 }, { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, + { GPMODE_DISCONNECT_PAGE, 0x0e, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -450,7 +457,8 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) swprintf(file_name, 512, L"cdrom_%02i_mode_sense_bin", dev->id); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { - fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + if (fread(dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f) != 0x10) + fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); fclose(f); } } @@ -561,6 +569,10 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) case 0x08: case 0x28: case 0xa8: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 11) << 11; + /* FALLTHROUGH */ + case 0xb9: case 0xbe: /* Make sure total length is not bigger than sum of the lengths of @@ -606,14 +618,15 @@ scsi_cdrom_bus_speed(scsi_cdrom_t *dev) { double ret = -1.0; - if (dev->drv->bus_type == CDROM_BUS_SCSI) { + if (dev && dev->drv && (dev->drv->bus_type == CDROM_BUS_SCSI)) { dev->callback = -1.0; /* Speed depends on SCSI controller */ return 0.0; } else { if (dev && dev->drv) ret = ide_atapi_get_period(dev->drv->ide_channel); if (ret == -1.0) { - dev->callback = -1.0; + if (dev) + dev->callback = -1.0; return 0.0; } else return ret * 1000000.0; @@ -666,6 +679,8 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) case 0xb8: case 0xb9: case 0xbe: + case 0xc6: + case 0xc7: if (dev->current_cdb[0] == 0x42) dev->callback += 40.0; /* Account for seek time. */ @@ -1078,29 +1093,31 @@ scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *pack return 0; } - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ + buf[4] = 18; /* Length of Layer Information */ + buf[5] = 0; + + buf[6] = 1; /* DVD-ROM, part version 1 */ + buf[7] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[8] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[9] = 0; /* default densities */ /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; + buf[10] = 0x00; + buf[11] = 0x03; + buf[12] = buf[13] = 0; /* start sector */ - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; + buf[14] = 0x00; + buf[15] = (total_sectors >> 16) & 0xff; /* end sector */ + buf[16] = (total_sectors >> 8) & 0xff; + buf[17] = total_sectors & 0xff; - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048 +2 ) >> 8) & 0xff; - buf[1] = (2048 + 2) & 0xff; + buf[18] = 0x00; + buf[19] = (total_sectors >> 16) & 0xff; /* l0 end sector */ + buf[20] = (total_sectors >> 8) & 0xff; + buf[21] = total_sectors & 0xff; - /* 2k data + 4 byte header */ - return (2048 + 4); + /* 20 bytes of data + 4 byte header */ + return (20 + 4); case 0x01: /* DVD copyright information */ buf[4] = 0; /* no copyright data */ @@ -1133,8 +1150,8 @@ scsi_cdrom_read_dvd_structure(scsi_cdrom_t *dev, int format, const uint8_t *pack buf[4] = 0x00; /* Physical format */ buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048 + 4) >> 8) & 0xff; - buf[7] = (2048 + 4) & 0xff; + buf[6] = ((20 + 4) >> 8) & 0xff; + buf[7] = (20 + 4) & 0xff; buf[8] = 0x01; /* Copyright info */ buf[9] = 0x40; /* Not writable, is readable */ @@ -1532,10 +1549,32 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) toc_format, ide->cylinder, dev->buffer[1]); */ return; + case GPCMD_READ_DISC_INFORMATION_TOSHIBA: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + scsi_cdrom_buf_alloc(dev, 65536); + + if ((!dev->drv->ops) && ((cdb[1] & 3) == 2)) { + scsi_cdrom_not_ready(dev); + return; + } + + memset(dev->buffer, 0, 4); + + cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); + + len = 4; + scsi_cdrom_set_buf_len(dev, BufLen, &len); + + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + return; + case GPCMD_READ_CD_OLD: /* IMPORTANT: Convert the command to new read CD for pass through purposes. */ dev->current_cdb[0] = 0xbe; + /*FALLTHROUGH*/ + case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: @@ -1891,7 +1930,7 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) } gesn_event_header->len = used_len - sizeof(*gesn_event_header); - memcpy(dev->buffer, gesn_event_header, 4); + memmove(dev->buffer, gesn_event_header, 4); scsi_cdrom_set_buf_len(dev, BufLen, &used_len); @@ -1970,6 +2009,36 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_data_command_finish(dev, len, len, max_len, 0); break; + case GPCMD_AUDIO_TRACK_SEARCH: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_audio_track_search(dev->drv, pos, cdb[9], cdb[1] & 1); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + + case GPCMD_TOSHIBA_PLAY_AUDIO: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + if ((dev->drv->host_drive < 1) || (dev->drv->cd_status <= CD_STATUS_DATA_ONLY)) { + scsi_cdrom_illegal_mode(dev); + break; + } + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + ret = cdrom_toshiba_audio_play(dev->drv, pos, cdb[9]); + + if (ret) + scsi_cdrom_command_complete(dev); + else + scsi_cdrom_illegal_mode(dev); + break; + case GPCMD_PLAY_AUDIO_10: case GPCMD_PLAY_AUDIO_12: case GPCMD_PLAY_AUDIO_MSF: @@ -1987,13 +2056,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) len = (cdb[7] << 8) | cdb[8]; break; case GPCMD_PLAY_AUDIO_12: + /* This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it. */ msf = 0; pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; break; case GPCMD_PLAY_AUDIO_MSF: - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ msf = 1; pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; @@ -2108,6 +2177,37 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_data_command_finish(dev, len, len, len, 0); break; + case GPCMD_READ_SUBCODEQ_PLAYING_STATUS: + scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); + + alloc_length = cdb[1] & 0x1f; + + scsi_cdrom_buf_alloc(dev, alloc_length); + + if (!dev->drv->ops) { + scsi_cdrom_not_ready(dev); + return; + } + + if (!alloc_length) { + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_log("CD-ROM %i: All done - callback set\n", dev->id); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * CDROM_TIME; + scsi_cdrom_set_callback(dev); + break; + } + + len = alloc_length; + + memset(dev->buffer, 0, len); + dev->buffer[0] = cdrom_get_current_subcodeq_playstatus(dev->drv, &dev->buffer[1]); + scsi_cdrom_log("Audio Status = %02x\n", dev->buffer[0]); + + scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); + scsi_cdrom_data_command_finish(dev, len, len, len, 0); + break; + case GPCMD_READ_DVD_STRUCTURE: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); @@ -2126,7 +2226,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if ((cdb[7] <= 0x7f) || (cdb[7] == 0xff)) { if (cdb[1] == 0) { ret = scsi_cdrom_read_dvd_structure(dev, format, cdb, dev->buffer); - if (ret) { + dev->buffer[0] = (ret >> 8); + dev->buffer[1] = (ret & 0xff); + dev->buffer[2] = dev->buffer[3] = 0x00; + if (ret) { scsi_cdrom_set_buf_len(dev, BufLen, &alloc_length); scsi_cdrom_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); @@ -2163,6 +2266,13 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) scsi_cdrom_command_complete(dev); break; + + case GPCMD_CADDY_EJECT: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + scsi_cdrom_stop(sc); + cdrom_eject(dev->id); + scsi_cdrom_command_complete(dev); + break; case GPCMD_INQUIRY: scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); @@ -2208,10 +2318,15 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[idx++] = 0x01; dev->buffer[idx++] = 0x00; dev->buffer[idx++] = 68; - ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */ + if (dev->drv->bus_type == CDROM_BUS_SCSI) + ide_padstr8(dev->buffer + idx, 8, "TOSHIBA"); /* Vendor */ + else + ide_padstr8(dev->buffer + idx, 8, EMU_NAME); /* Vendor */ idx += 8; - ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */ - + if (dev->drv->bus_type == CDROM_BUS_SCSI) + ide_padstr8(dev->buffer + idx, 40, "XM6201TASUN32XCD1103"); /* Product */ + else + ide_padstr8(dev->buffer + idx, 40, device_identify_ex); /* Product */ idx += 40; ide_padstr8(dev->buffer + idx, 20, "53R141"); /* Product */ idx += 20; @@ -2244,10 +2359,16 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) dev->buffer[6] = 1; /* 16-bit transfers supported */ dev->buffer[7] = 0x20; /* Wide bus supported */ } - - ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->buffer + 32, 4, EMU_VERSION); /* Revision */ + + if (dev->drv->bus_type == CDROM_BUS_SCSI) { + ide_padstr8(dev->buffer + 8, 8, "TOSHIBA"); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, "XM6201TASUN32XCD"); /* Product */ + ide_padstr8(dev->buffer + 32, 4, "1103"); /* Revision */ + } else { + ide_padstr8(dev->buffer + 8, 8, EMU_NAME); /* Vendor */ + ide_padstr8(dev->buffer + 16, 16, device_identify); /* Product */ + ide_padstr8(dev->buffer + 32, 4, EMU_VERSION); /* Revision */ + } idx = 36; @@ -2272,13 +2393,21 @@ atapi_out: scsi_cdrom_command_complete(dev); break; +#if 0 case GPCMD_PAUSE_RESUME_ALT: +#endif case GPCMD_PAUSE_RESUME: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); cdrom_audio_pause_resume(dev->drv, cdb[8] & 0x01); scsi_cdrom_command_complete(dev); break; + case GPCMD_STILL: + scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); + dev->drv->cd_status = CD_STATUS_PAUSED; + scsi_cdrom_command_complete(dev); + break; + case GPCMD_SEEK_6: case GPCMD_SEEK_10: scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2545,7 +2674,7 @@ scsi_cdrom_drive_reset(int c) ide_t *id; /* Make sure to ignore any SCSI CD-ROM drive that has an out of range ID. */ - if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->scsi_device_id > SCSI_ID_MAX)) + if ((drv->bus_type == CDROM_BUS_SCSI) && (drv->scsi_device_id >= SCSI_ID_MAX)) return; /* Make sure to ignore any ATAPI CD-ROM drive that has an out of range IDE channel. */ diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index c0fe14694..61aca0b81 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -20,9 +20,9 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../disk/hdd.h" +#include "86box.h" +#include "device.h" +#include "hdd.h" #include "scsi.h" #include "scsi_device.h" diff --git a/src/scsi/scsi_device.h b/src/scsi/scsi_device.h index 5527dae0e..181e4ea7e 100644 --- a/src/scsi/scsi_device.h +++ b/src/scsi/scsi_device.h @@ -8,7 +8,7 @@ * * Definitions for the generic SCSI device command handler. * - * Version: @(#)scsi_device.h 1.0.17 2019/09/26 + * Version: @(#)scsi_device.h 1.0.18 2020/03/23 * * Authors: Miran Grca, * Fred N. van Kempen, @@ -102,8 +102,14 @@ #define GPCMD_PLAY_CD 0xbc #define GPCMD_MECHANISM_STATUS 0xbd #define GPCMD_READ_CD 0xbe -#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */ +#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to 86Box. */ +#define GPCMD_AUDIO_TRACK_SEARCH 0xc0 /* Toshiba Vendor Unique command */ +#define GPCMD_TOSHIBA_PLAY_AUDIO 0xc1 /* Toshiba Vendor Unique command */ #define GPCMD_PAUSE_RESUME_ALT 0xc2 +#define GPCMD_STILL 0xc2 /* Toshiba Vendor Unique command */ +#define GPCMD_CADDY_EJECT 0xc4 /* Toshiba Vendor Unique command */ +#define GPCMD_READ_SUBCODEQ_PLAYING_STATUS 0xc6 /* Toshiba Vendor Unique command */ +#define GPCMD_READ_DISC_INFORMATION_TOSHIBA 0xc7 /* Toshiba Vendor Unique command */ #define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ #define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 91256b4dc..a8fcc73bc 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -19,17 +19,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../device.h" -#include "../nvr.h" -#include "../piix.h" -#include "../disk/hdd.h" -#include "../disk/hdc.h" +#include "86box.h" +#include "timer.h" +#include "device.h" +#include "nvr.h" +#include "piix.h" +#include "hdd.h" +#include "hdc.h" #include "scsi_device.h" -#include "../disk/hdc_ide.h" -#include "../plat.h" -#include "../ui.h" +#include "hdc_ide.h" +#include "plat.h" +#include "ui.h" #include "scsi_disk.h" @@ -155,7 +155,8 @@ scsi_disk_mode_sense_load(scsi_disk_t *dev) swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); f = plat_fopen(nvr_path(file_name), L"rb"); if (f) { - fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); + if (fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f) != 0x18) + fatal("scsi_disk_mode_sense_load(): Error reading data\n"); fclose(f); } } @@ -613,6 +614,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) scsi_disk_invalid_field(dev); return; } + /*FALLTHROUGH*/ case GPCMD_SCSI_RESERVE: case GPCMD_SCSI_RELEASE: case GPCMD_TEST_UNIT_READY: @@ -1212,7 +1214,7 @@ scsi_disk_hard_reset(void) scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); /* Make sure to ignore any SCSI disk that has an out of range ID. */ - if (hdd[c].scsi_id > SCSI_ID_MAX) + if (hdd[c].scsi_id >= SCSI_ID_MAX) continue; /* Make sure to ignore any SCSI disk whose image file name is empty. */ diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index a2991cce8..9a652e8e1 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -27,17 +27,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../dma.h" -#include "../pic.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "mca.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "plat.h" #include "scsi.h" #include "scsi_device.h" #include "scsi_ncr5380.h" @@ -430,7 +430,7 @@ ncr_bus_update(void *priv, int bus) ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { - if (ncr->msglun >= 0 && ncr->is_msgout) { + if (ncr->is_msgout) { ncr->is_msgout = 0; ncr->command[1] &= ~(0x80 | 0x40 | 0x20); ncr->command[1] |= ncr->msglun << 5; diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index 56af023a1..77c9d0143 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -32,25 +32,28 @@ #include #define HAVE_STDARG_H #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../dma.h" -#include "../pic.h" -#include "../mem.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../nvr.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "mem.h" +#include "rom.h" +#include "pci.h" +#include "device.h" +#include "nvr.h" +#include "plat.h" #include "scsi.h" #include "scsi_device.h" #include "scsi_ncr53c8xx.h" #define NCR53C8XX_ROM L"roms/scsi/ncr53c8xx/NCR307.BIN" +#define HA_ID 7 + #define CHIP_810 0x01 #define CHIP_825 0x03 +#define CHIP_860 0x06 #define CHIP_875 0x0f #define NCR_SCNTL0_TRG 0x01 @@ -302,6 +305,10 @@ typedef struct { uint32_t adder; pc_timer_t timer; + +#ifdef USE_WDTR + uint8_t tr_set[16]; +#endif } ncr53c8xx_t; @@ -401,7 +408,7 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) dev->scntl3 = 0; dev->sstat0 = 0; dev->sstat1 = 0; - dev->scid = 7; + dev->scid = HA_ID; dev->sxfer = 0; dev->socl = 0; dev->sdid = 0; @@ -428,13 +435,21 @@ ncr53c8xx_soft_reset(ncr53c8xx_t *dev) if (dev->chip >= CHIP_825) { /* This *IS* a wide SCSI controller, so reset all SCSI devices. */ - for (i = 0; i < 16; i++) + for (i = 0; i < 16; i++) { +#ifdef USE_WDTR + dev->tr_set[i] = 0; +#endif scsi_device_reset(&scsi_devices[i]); + } } else { /* This is *NOT* a wide SCSI controller, so do not touch SCSI devices with ID's >= 8. */ - for (i = 0; i < 8; i++) + for (i = 0; i < 8; i++) { +#ifdef USE_WDTR + dev->tr_set[i] = 0; +#endif scsi_device_reset(&scsi_devices[i]); + } } } @@ -802,9 +817,9 @@ ncr53c8xx_do_wdtr(ncr53c8xx_t *dev, int exponent) ncr53c8xx_log("Target-initiated WDTR (%08X)\n", dev); ncr53c8xx_set_phase(dev, PHASE_MI); dev->msg_action = 4; - ncr53c8xx_add_msg_byte(dev, 0x01); /* EXTENDED MESSAGE */ - ncr53c8xx_add_msg_byte(dev, 0x02); /* EXTENDED MESSAGE LENGTH */ - ncr53c8xx_add_msg_byte(dev, 0x03); /* WIDE DATA TRANSFER REQUEST */ + ncr53c8xx_add_msg_byte(dev, 0x01); /* EXTENDED MESSAGE */ + ncr53c8xx_add_msg_byte(dev, 0x02); /* EXTENDED MESSAGE LENGTH */ + ncr53c8xx_add_msg_byte(dev, 0x03); /* WIDE DATA TRANSFER REQUEST */ ncr53c8xx_add_msg_byte(dev, exponent); /* TRANSFER WIDTH EXPONENT (16-bit) */ } #endif @@ -925,13 +940,14 @@ ncr53c8xx_do_msgout(ncr53c8xx_t *dev, uint8_t id) break; case 3: ncr53c8xx_log("WDTR (ignored)\n"); +#ifdef USE_WDTR + dev->tr_set[dev->sdid] = 1; +#endif if (arg > 0x01) { ncr53c8xx_bad_message(dev, msg); return; } -#ifdef USE_WDTR ncr53c8xx_set_phase(dev, PHASE_CMD); -#endif break; case 5: ncr53c8xx_log("PPR (ignored)\n"); @@ -960,9 +976,14 @@ ncr53c8xx_do_msgout(ncr53c8xx_t *dev, uint8_t id) scsi_device_command_stop(sd); ncr53c8xx_disconnect(dev); break; + case 0x0c: + /* BUS DEVICE RESET message, reset wide transfer request. */ +#ifdef USE_WDTR + dev->tr_set[dev->sdid] = 0; +#endif + /* FALLTHROUGH */ case 0x06: case 0x0e: - case 0x0c: /* clear the current I/O process */ scsi_device_command_stop(sd); ncr53c8xx_disconnect(dev); @@ -977,10 +998,11 @@ ncr53c8xx_do_msgout(ncr53c8xx_t *dev, uint8_t id) dev->current_lun = msg & 7; ncr53c8xx_log("Select LUN %d\n", dev->current_lun); #ifdef USE_WDTR - ncr53c8xx_do_wdtr(dev, 0x01); -#else - ncr53c8xx_set_phase(dev, PHASE_CMD); + if ((dev->chip == CHIP_875) && !dev->tr_set[dev->sdid]) + ncr53c8xx_do_wdtr(dev, 0x01); + else #endif + ncr53c8xx_set_phase(dev, PHASE_CMD); } break; } @@ -2625,6 +2647,7 @@ ncr53c8xx_init(const device_t *info) ncr53c8xx_pci_bar[0].addr_regs[0] = 1; ncr53c8xx_pci_bar[1].addr_regs[0] = 0; dev->chip = info->local; + ncr53c8xx_pci_regs[0x04] = 3; ncr53c8xx_mem_init(dev, 0x0fffff00); @@ -2632,12 +2655,14 @@ ncr53c8xx_init(const device_t *info) dev->has_bios = device_get_config_int("bios"); if (dev->has_bios) - rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); if (dev->chip >= CHIP_825) { - if (dev->chip == CHIP_875) { dev->chip_rev = 0x04; dev->nvr_path = L"ncr53c875.nvr"; + } else if (dev->chip == CHIP_860) { + dev->chip_rev = 0x04; + dev->nvr_path = L"ncr53c860.nvr"; } else { dev->chip_rev = 0x26; dev->nvr_path = L"ncr53c825a.nvr"; @@ -2654,8 +2679,8 @@ ncr53c8xx_init(const device_t *info) ncr53c8xx_bios_disable(dev); #endif } else { - if (dev->has_bios) - rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + /* if (dev->has_bios) + rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); */ dev->nvr_path = L"ncr53c810.nvr"; } @@ -2715,6 +2740,16 @@ const device_t ncr53c825a_pci_device = ncr53c8xx_pci_config }; +const device_t ncr53c860_pci_device = +{ + "NCR 53c860 (SCSI)", + DEVICE_PCI, + CHIP_860, + ncr53c8xx_init, ncr53c8xx_close, NULL, + NULL, NULL, NULL, + ncr53c8xx_pci_config +}; + const device_t ncr53c875_pci_device = { "NCR 53c875 (SCSI)", diff --git a/src/scsi/scsi_ncr53c8xx.h b/src/scsi/scsi_ncr53c8xx.h index e50e6d954..b84c91c1c 100644 --- a/src/scsi/scsi_ncr53c8xx.h +++ b/src/scsi/scsi_ncr53c8xx.h @@ -27,6 +27,7 @@ extern const device_t ncr53c810_pci_device; extern const device_t ncr53c825a_pci_device; +extern const device_t ncr53c860_pci_device; extern const device_t ncr53c875_pci_device; diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c new file mode 100644 index 000000000..1a26b6b49 --- /dev/null +++ b/src/scsi/scsi_spock.c @@ -0,0 +1,1160 @@ +/* + * 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 IBM PS/2 SCSI controller with + * cache for MCA only. + * + * Version: @(#)scsi_spock.c 1.0.1 2020/03/23 + * + * Authors: Sarah Walker, + * TheCollector1995, + * + * Copyright 2020 Sarah Walker. + * Copyright 2020 TheCollector1995. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "mca.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "plat.h" +#include "scsi.h" +#include "scsi_device.h" +#include "scsi_spock.h" + +#define SPOCK_U68_1990_ROM L"roms/scsi/ibm/64f4376.bin" +#define SPOCK_U69_1990_ROM L"roms/scsi/ibm/64f4377.bin" + +#define SPOCK_U68_1991_ROM L"roms/scsi/ibm/92F2244.U68" +#define SPOCK_U69_1991_ROM L"roms/scsi/ibm/92F2245.U69" + +#define SPOCK_TIME (20) + +typedef enum +{ + SCSI_STATE_IDLE, + SCSI_STATE_SELECT, + SCSI_STATE_SELECT_FAILED, + SCSI_STATE_SEND_COMMAND, + SCSI_STATE_END_PHASE +} scsi_state_t; + +#pragma pack(push,1) +typedef struct { + uint16_t pos; + uint16_t pos2; + uint16_t pos3; + uint16_t pos4; + uint16_t pos5; + uint16_t pos6; + uint16_t pos7; + uint16_t pos8; +} get_pos_info_t; + +typedef struct { + uint16_t scb_status; + uint16_t retry_count; + uint32_t residual_byte_count; + uint32_t sg_list_element_addr; + uint16_t device_dep_status_len; + uint16_t cmd_status; + uint16_t error; + uint16_t reserved; + uint16_t cache_info_status; + uint32_t scb_addr; +} get_complete_stat_t; + +typedef struct { + uint32_t sys_buf_addr; + uint32_t sys_buf_byte_count; +} SGE; + +typedef struct { + uint16_t command; + uint16_t enable; + uint32_t lba_addr; + SGE sge; + uint32_t term_status_block_addr; + uint32_t scb_chain_addr; + uint16_t block_count; + uint16_t block_length; +} scb_t; +#pragma pack(pop) + +typedef struct { + rom_t bios_rom; + + int bios_ver; + int irq, irq_inactive; + + uint8_t pos_regs[8]; + + uint8_t basic_ctrl; + uint32_t command; + + uint8_t attention, + attention_pending; + int attention_wait; + + uint8_t cir[4], + cir_pending[4]; + + uint8_t irq_status; + + uint32_t scb_addr; + + uint8_t status; + + get_complete_stat_t get_complete_stat; + get_pos_info_t get_pos_info; + + scb_t scb; + int scb_id; + + int cmd_status; + int cir_status; + + uint8_t pacing; + + uint8_t buf[0x600]; + + struct { + int phys_id; + int lun_id; + } dev_id[SCSI_ID_MAX]; + + uint8_t last_status; + uint8_t cdb[12]; + int cdb_len; + int cdb_id; + uint32_t data_ptr, data_len; + uint8_t temp_cdb[12]; + + int irq_requests[SCSI_ID_MAX]; + + pc_timer_t callback_timer; + + int cmd_timer; + + int scb_state; + int in_reset; + int in_invalid; + + uint64_t temp_period; + double media_period; + + scsi_state_t scsi_state; +} spock_t; + +#define CTRL_RESET (1 << 7) +#define CTRL_DMA_ENA (1 << 1) +#define CTRL_IRQ_ENA (1 << 0) + +#define STATUS_CMD_FULL (1 << 3) +#define STATUS_CMD_EMPTY (1 << 2) +#define STATUS_IRQ (1 << 1) +#define STATUS_BUSY (1 << 0) + +#define ENABLE_PT (1 << 12) + +#define CMD_MASK 0xff3f +#define CMD_ASSIGN 0x040e +#define CMD_DEVICE_INQUIRY 0x1c0b +#define CMD_DMA_PACING_CONTROL 0x040d +#define CMD_FEATURE_CONTROL 0x040c +#define CMD_GET_POS_INFO 0x1c0a +#define CMD_INVALID_412 0x0412 +#define CMD_GET_COMPLETE_STATUS 0x1c07 +#define CMD_FORMAT_UNIT 0x1c16 +#define CMD_READ_DATA 0x1c01 +#define CMD_READ_DEVICE_CAPACITY 0x1c09 +#define CMD_REQUEST_SENSE 0x1c08 +#define CMD_RESET 0x0400 +#define CMD_SEND_OTHER_SCSI 0x241f +#define CMD_UNKNOWN_1C10 0x1c10 +#define CMD_UNKNOWN_1C11 0x1c11 +#define CMD_WRITE_DATA 0x1c02 +#define CMD_VERIFY 0x1c03 + +#define IRQ_TYPE_NONE 0x0 +#define IRQ_TYPE_SCB_COMPLETE 0x1 +#define IRQ_TYPE_SCB_COMPLETE_RETRY 0x5 +#define IRQ_TYPE_ADAPTER_HW_FAILURE 0x7 +#define IRQ_TYPE_IMM_CMD_COMPLETE 0xa +#define IRQ_TYPE_COMMAND_FAIL 0xc +#define IRQ_TYPE_COMMAND_ERROR 0xe +#define IRQ_TYPE_SW_SEQ_ERROR 0xf +#define IRQ_TYPE_RESET_COMPLETE 0x10 + + +#ifdef ENABLE_SPOCK_LOG +int spock_do_log = ENABLE_SPOCK_LOG; + + +static void +spock_log(const char *fmt, ...) +{ + va_list ap; + + if (spock_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define spock_log(fmt, ...) +#endif + +static void +spock_rethink_irqs(spock_t *scsi) +{ + int irq_pending = 0; + int c; + + if (!scsi->irq_status) { + for (c = 0; c < SCSI_ID_MAX; c++) { + if (scsi->irq_requests[c] != IRQ_TYPE_NONE) { + /* Found IRQ */ + scsi->irq_status = c | (scsi->irq_requests[c] << 4); + spock_log("Found IRQ: status = %02x\n", scsi->irq_status); + scsi->status |= STATUS_IRQ; + irq_pending = 1; + break; + } + } + } else + irq_pending = 1; + + if (scsi->basic_ctrl & CTRL_IRQ_ENA) { + if (irq_pending) { + spock_log("IRQ issued\n"); + scsi->irq_inactive = 0; + picint(1 << scsi->irq); + } else { + /* No IRQs pending, clear IRQ state */ + spock_log("IRQ cleared\n"); + scsi->irq_status = 0; + scsi->irq_inactive = 1; + scsi->status &= ~STATUS_IRQ; + picintc(1 << scsi->irq); + } + } else { + spock_log("IRQ disabled\n"); + picintc(1 << scsi->irq); + } +} + +static __inline void +spock_set_irq(spock_t *scsi, int id, int type) +{ + spock_log("spock_set_irq id=%i type=%x %02x\n", id, type, scsi->irq_status); + scsi->irq_requests[id] = type; + if (!scsi->irq_status) /* Don't change IRQ status if one is currently being processed */ + spock_rethink_irqs(scsi); +} + +static __inline void +spock_clear_irq(spock_t *scsi, int id) +{ + spock_log("spock_clear_irq id=%i\n", id); + scsi->irq_requests[id] = IRQ_TYPE_NONE; + spock_rethink_irqs(scsi); +} + +static void +spock_add_to_period(spock_t *scsi, int TransferLength) +{ + scsi->temp_period += (uint64_t) TransferLength; +} + +static void +spock_write(uint16_t port, uint8_t val, void *p) +{ + spock_t *scsi = (spock_t *)p; + + spock_log("spock_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); + + switch (port & 7) { + case 0: case 1: case 2: case 3: /*Command Interface Register*/ + scsi->cir_pending[port & 3] = val; + if (port & 2) + scsi->cir_status |= 2; + else + scsi->cir_status |= 1; + break; + + case 4: /*Attention Register*/ + scsi->attention_pending = val; + scsi->attention_wait = 2; + scsi->status |= STATUS_BUSY; + break; + + case 5: /*Basic Control Register*/ + if ((scsi->basic_ctrl & CTRL_RESET) && !(val & CTRL_RESET)) { + spock_log("Spock: SCSI reset and busy\n"); + scsi->in_reset = 1; + scsi->cmd_timer = SPOCK_TIME * 2; + scsi->status |= STATUS_BUSY; + } + scsi->basic_ctrl = val; + spock_rethink_irqs(scsi); + break; + } +} + +static void +spock_writew(uint16_t port, uint16_t val, void *p) +{ + spock_t *scsi = (spock_t *)p; + + switch (port & 7) { + case 0: /*Command Interface Register*/ + scsi->cir_pending[0] = val & 0xff; + scsi->cir_pending[1] = val >> 8; + scsi->cir_status |= 1; + break; + case 2: /*Command Interface Register*/ + scsi->cir_pending[2] = val & 0xff; + scsi->cir_pending[3] = val >> 8; + scsi->cir_status |= 2; + break; + } + + spock_log("spock_writew: port=%04x val=%04x\n", port, val); +} + + +static uint8_t +spock_read(uint16_t port, void *p) +{ + spock_t *scsi = (spock_t *)p; + uint8_t temp = 0xff; + + switch (port & 7) { + case 0: case 1: case 2: case 3: /*Command Interface Register*/ + temp = scsi->cir_pending[port & 3]; + break; + + case 4: /*Attention Register*/ + temp = scsi->attention_pending; + break; + case 5: /*Basic Control Register*/ + temp = scsi->basic_ctrl; + break; + case 6: /*IRQ status*/ + temp = scsi->irq_status; + break; + case 7: /*Basic Status Register*/ + temp = scsi->status; + if (scsi->cir_status == 0) { + spock_log("Status Cmd Empty\n"); + temp |= STATUS_CMD_EMPTY; + } + if (scsi->cir_status == 3) { + spock_log("Status Cmd Full\n"); + temp |= STATUS_CMD_FULL; + } + break; + } + + spock_log("spock_read: port=%04x val=%02x %04x(%05x):%04x %02x\n", port, temp, CS, cs, cpu_state.pc, BH); + return temp; +} + +static uint16_t +spock_readw(uint16_t port, void *p) +{ + spock_t *scsi = (spock_t *)p; + uint16_t temp = 0xffff; + + switch (port & 7) { + case 0: /*Command Interface Register*/ + temp = scsi->cir_pending[0] | (scsi->cir_pending[1] << 8); + break; + case 2: /*Command Interface Register*/ + temp = scsi->cir_pending[2] | (scsi->cir_pending[3] << 8); + break; + } + + spock_log("spock_readw: port=%04x val=%04x\n", port, temp); + return temp; +} + +static void +spock_rd_sge(spock_t *scsi, uint32_t Address, SGE *SG) +{ + DMAPageRead(Address, (uint8_t *)SG, sizeof(SGE)); + spock_add_to_period(scsi, sizeof(SGE)); +} + +static int +spock_get_len(spock_t *scsi, scb_t *scb) +{ + uint32_t DataToTransfer = 0, i = 0; + + spock_log("Data Buffer write: length %d, pointer 0x%04X\n", + scsi->data_len, scsi->data_ptr); + + if (!scsi->data_len) + return(0); + + if (scb->enable & ENABLE_PT) { + for (i = 0; i < scsi->data_len; i += 8) { + spock_rd_sge(scsi, scsi->data_ptr + i, &scb->sge); + + DataToTransfer += scb->sge.sys_buf_byte_count; + } + return(DataToTransfer); + } else { + return(scsi->data_len); + } +} + +static void +spock_process_imm_cmd(spock_t *scsi) +{ + int i; + int adapter_id, phys_id, lun_id; + + switch (scsi->command & CMD_MASK) { + case CMD_ASSIGN: + adapter_id = (scsi->command >> 16) & 15; + phys_id = (scsi->command >> 20) & 7; + lun_id = (scsi->command >> 24) & 7; + + if (adapter_id == 15) { + if (phys_id == 7) /*Device 15 always adapter*/ + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + else /*Can not re-assign device 15 (always adapter)*/ + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); + } else { + if (scsi->command & (1 << 23)) { + spock_log("Physical Device Number -1\n"); + scsi->dev_id[adapter_id].phys_id = -1; + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + } else if (phys_id == 7) { /*Can not assign adapter*/ + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_FAIL); + } else { + scsi->dev_id[adapter_id].phys_id = phys_id; + scsi->dev_id[adapter_id].lun_id = lun_id; + spock_log("Assign: adapter dev=%x scsi ID=%i LUN=%i\n", adapter_id, scsi->dev_id[adapter_id].phys_id, scsi->dev_id[adapter_id].lun_id); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + } + } + break; + + case CMD_DMA_PACING_CONTROL: + scsi->pacing = scsi->cir[2]; + spock_log("Pacing control: %i\n", scsi->pacing); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + + case CMD_FEATURE_CONTROL: + spock_log("Feature control: timeout=%is d-rate=%i\n", (scsi->command >> 16) & 0x1fff, scsi->command >> 29); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + + case CMD_INVALID_412: + spock_log("Invalid 412\n"); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + + case CMD_RESET: + spock_log("Reset Command\n"); + if ((scsi->attention & 15) == 15) { /*Adapter reset*/ + for (i = 0; i < 7; i++) + scsi_device_reset(&scsi_devices[i]); + spock_log("Adapter Reset\n"); + + scsi->scb_state = 0; + } + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_IMM_CMD_COMPLETE); + break; + + default: + fatal("scsi_callback: Bad command %02x\n", scsi->command); + break; + } +} + +static void +spock_execute_cmd(spock_t *scsi, scb_t *scb) +{ + int c; + int old_scb_state; + + if (scsi->in_reset) { + spock_log("Reset type = %d\n", scsi->in_reset); + + scsi->status &= ~STATUS_BUSY; + scsi->irq_status = 0; + + for (c = 0; c < SCSI_ID_MAX; c++) + spock_clear_irq(scsi, c); + + if (scsi->in_reset == 1) { + scsi->basic_ctrl |= CTRL_IRQ_ENA; + spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); + } else + spock_set_irq(scsi, 0x0f, IRQ_TYPE_RESET_COMPLETE); + + /*Reset device mappings*/ + for (c = 0; c < 7; c++) { + scsi->dev_id[c].phys_id = c; + scsi->dev_id[c].lun_id = 0; + } + for (; c < (SCSI_ID_MAX-1); c++) + scsi->dev_id[c].phys_id = -1; + + scsi->in_reset = 0; + return; + } + + if (scsi->in_invalid) { + spock_log("Invalid command\n"); + spock_set_irq(scsi, scsi->attention & 0x0f, IRQ_TYPE_COMMAND_ERROR); + scsi->in_invalid = 0; + return; + } + + do + { + old_scb_state = scsi->scb_state; + + switch (scsi->scb_state) { + case 0: /* Idle */ + break; + + case 1: /* Select */ + if (scsi->dev_id[scsi->scb_id].phys_id == -1) { + uint16_t term_stat_block_addr7 = (0xe << 8) | 0; + uint16_t term_stat_block_addr8 = (0xa << 8) | 0; + + spock_log("Start failed, SCB ID = %d\n", scsi->scb_id); + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + DMAPageWrite(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2); + DMAPageWrite(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2); + break; + } + + DMAPageRead(scsi->scb_addr, (uint8_t *)&scb->command, 2); + DMAPageRead(scsi->scb_addr + 2, (uint8_t *)&scb->enable, 2); + DMAPageRead(scsi->scb_addr + 4, (uint8_t *)&scb->lba_addr, 4); + DMAPageRead(scsi->scb_addr + 8, (uint8_t *)&scb->sge.sys_buf_addr, 4); + DMAPageRead(scsi->scb_addr + 12, (uint8_t *)&scb->sge.sys_buf_byte_count, 4); + DMAPageRead(scsi->scb_addr + 16, (uint8_t *)&scb->term_status_block_addr, 4); + DMAPageRead(scsi->scb_addr + 20, (uint8_t *)&scb->scb_chain_addr, 4); + DMAPageRead(scsi->scb_addr + 24, (uint8_t *)&scb->block_count, 2); + DMAPageRead(scsi->scb_addr + 26, (uint8_t *)&scb->block_length, 2); + + spock_log("SCB : \n" + " Command = %04x\n" + " Enable = %04x\n" + " LBA addr = %08x\n" + " System buffer addr = %08x\n" + " System buffer byte count = %08x\n" + " Terminate status block addr = %08x\n" + " SCB chain address = %08x\n" + " Block count = %04x\n" + " Block length = %04x\n", + scb->command, scb->enable, scb->lba_addr, + scb->sge.sys_buf_addr, scb->sge.sys_buf_byte_count, + scb->term_status_block_addr, scb->scb_chain_addr, + scb->block_count, scb->block_length); + + if (scb->command == 0x245f) { /*Issued by NT October 1991 and December 1991 (Undocumented version of Send Other SCSI?)*/ + spock_log("Send Other SCSI (BIOS?)\n"); + scb->command = CMD_SEND_OTHER_SCSI; + } + + switch (scb->command & CMD_MASK) { + case CMD_GET_COMPLETE_STATUS: + { + spock_log("Get Complete Status\n"); + get_complete_stat_t *get_complete_stat = &scsi->get_complete_stat; + + get_complete_stat->scb_status = 0x201; + get_complete_stat->retry_count = 0; + get_complete_stat->residual_byte_count = 0; + get_complete_stat->sg_list_element_addr = 0; + get_complete_stat->device_dep_status_len = 0x0c; + get_complete_stat->cmd_status = scsi->cmd_status << 8; + get_complete_stat->error = 0; + get_complete_stat->reserved = 0; + get_complete_stat->cache_info_status = 0; + get_complete_stat->scb_addr = scsi->scb_addr; + + DMAPageWrite(scb->sge.sys_buf_addr, (uint8_t *)&get_complete_stat->scb_status, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 2, (uint8_t *)&get_complete_stat->retry_count, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 4, (uint8_t *)&get_complete_stat->residual_byte_count, 4); + DMAPageWrite(scb->sge.sys_buf_addr + 8, (uint8_t *)&get_complete_stat->sg_list_element_addr, 4); + DMAPageWrite(scb->sge.sys_buf_addr + 12, (uint8_t *)&get_complete_stat->device_dep_status_len, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 14, (uint8_t *)&get_complete_stat->cmd_status, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 16, (uint8_t *)&get_complete_stat->error, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 18, (uint8_t *)&get_complete_stat->reserved, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 20, (uint8_t *)&get_complete_stat->cache_info_status, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 22, (uint8_t *)&get_complete_stat->scb_addr, 4); + scsi->scb_state = 3; + } + break; + + case CMD_UNKNOWN_1C10: + spock_log("Unknown 1C10\n"); + DMAPageRead(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count); + scsi->scb_state = 3; + break; + + case CMD_UNKNOWN_1C11: + spock_log("Unknown 1C11\n"); + DMAPageWrite(scb->sge.sys_buf_addr, scsi->buf, scb->sge.sys_buf_byte_count); + scsi->scb_state = 3; + break; + + case CMD_GET_POS_INFO: + { + spock_log("Get POS Info\n"); + get_pos_info_t *get_pos_info = &scsi->get_pos_info; + + get_pos_info->pos = 0x8eff; + get_pos_info->pos2 = scsi->pos_regs[3] | (scsi->pos_regs[2] << 8); + get_pos_info->pos3 = 0x0e | (scsi->pos_regs[4] << 8); + get_pos_info->pos4 = 1 << 12; + get_pos_info->pos4 = (7 << 8) | 8; + get_pos_info->pos5 = (16 << 8) | scsi->pacing; + get_pos_info->pos6 = (30 << 8) | 1; + get_pos_info->pos7 = 0; + get_pos_info->pos8 = 0; + + DMAPageWrite(scb->sge.sys_buf_addr, (uint8_t *)&get_pos_info->pos, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 2, (uint8_t *)&get_pos_info->pos2, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 4, (uint8_t *)&get_pos_info->pos3, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 6, (uint8_t *)&get_pos_info->pos4, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 8, (uint8_t *)&get_pos_info->pos5, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 10, (uint8_t *)&get_pos_info->pos6, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 12, (uint8_t *)&get_pos_info->pos7, 2); + DMAPageWrite(scb->sge.sys_buf_addr + 14, (uint8_t *)&get_pos_info->pos8, 2); + scsi->scb_state = 3; + } + break; + + case CMD_DEVICE_INQUIRY: + spock_log("Device Inquiry\n"); + scsi->cdb[0] = GPCMD_INQUIRY; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; /*Page code*/ + scsi->cdb[3] = 0; + scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ + scsi->cdb[5] = 0; /*Control*/ + scsi->cdb_len = 6; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->data_ptr = scb->sge.sys_buf_addr; + scsi->data_len = scb->sge.sys_buf_byte_count; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_SEND_OTHER_SCSI: + spock_log("Send Other SCSI\n"); + DMAPageRead(scsi->scb_addr + 0x18, scsi->cdb, 12); + scsi->cdb[1] = (scsi->cdb[1] & 0x1f) | (scsi->dev_id[scsi->scb_id].lun_id << 5); /*Patch correct LUN into command*/ + scsi->cdb_len = (scb->lba_addr & 0xff) ? (scb->lba_addr & 0xff) : 6; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_READ_DEVICE_CAPACITY: + spock_log("Device Capacity\n"); + scsi->cdb[0] = GPCMD_READ_CDROM_CAPACITY; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; /*LBA*/ + scsi->cdb[3] = 0; + scsi->cdb[4] = 0; + scsi->cdb[5] = 0; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = 0; + scsi->cdb[8] = 0; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_READ_DATA: + spock_log("Device Read Data\n"); + scsi->cdb[0] = GPCMD_READ_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_WRITE_DATA: + spock_log("Device Write Data\n"); + scsi->cdb[0] = GPCMD_WRITE_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_VERIFY: + spock_log("Device Verify\n"); + scsi->cdb[0] = GPCMD_VERIFY_10; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = (scb->lba_addr >> 24) & 0xff; /*LBA*/ + scsi->cdb[3] = (scb->lba_addr >> 16) & 0xff; + scsi->cdb[4] = (scb->lba_addr >> 8) & 0xff; + scsi->cdb[5] = scb->lba_addr & 0xff; + scsi->cdb[6] = 0; /*Reserved*/ + scsi->cdb[7] = (scb->block_count >> 8) & 0xff; + scsi->cdb[8] = scb->block_count & 0xff; + scsi->cdb[9] = 0; /*Control*/ + scsi->cdb_len = 10; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->data_len = 0; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + + case CMD_REQUEST_SENSE: + spock_log("Device Request Sense\n"); + scsi->cdb[0] = GPCMD_REQUEST_SENSE; + scsi->cdb[1] = scsi->dev_id[scsi->scb_id].lun_id << 5; /*LUN*/ + scsi->cdb[2] = 0; + scsi->cdb[3] = 0; + scsi->cdb[4] = scb->sge.sys_buf_byte_count; /*Allocation length*/ + scsi->cdb[5] = 0; + scsi->cdb_len = 6; + scsi->cdb_id = scsi->dev_id[scsi->scb_id].phys_id; + scsi->scsi_state = SCSI_STATE_SELECT; + scsi->scb_state = 2; + return; + } + break; + + case 2: /* Wait */ + if (scsi->scsi_state == SCSI_STATE_IDLE) { + if (scsi->last_status == SCSI_STATUS_OK) { + scsi->scb_state = 3; + spock_log("Status is Good on device ID %d\n", scsi->cdb_id); + } else if (scsi->last_status == SCSI_STATUS_CHECK_CONDITION) { + uint16_t term_stat_block_addr7 = (0xc << 8) | 2; + uint16_t term_stat_block_addr8 = 0x20; + uint16_t term_stat_block_addrb = scsi->scb_addr & 0xffff; + uint16_t term_stat_block_addrc = scsi->scb_addr >> 16; + + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + spock_log("Status Check Condition on device ID %d\n", scsi->cdb_id); + DMAPageWrite(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2); + DMAPageWrite(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2); + DMAPageWrite(scb->term_status_block_addr + 0xb*2, (uint8_t *)&term_stat_block_addrb, 2); + DMAPageWrite(scb->term_status_block_addr + 0xc*2, (uint8_t *)&term_stat_block_addrc, 2); + } + } else if (scsi->scsi_state == SCSI_STATE_SELECT_FAILED) { + uint16_t term_stat_block_addr7 = (0xc << 8) | 2; + uint16_t term_stat_block_addr8 = 0x10; + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_COMMAND_FAIL); + scsi->scb_state = 0; + DMAPageWrite(scb->term_status_block_addr + 0x7*2, (uint8_t *)&term_stat_block_addr7, 2); + DMAPageWrite(scb->term_status_block_addr + 0x8*2, (uint8_t *)&term_stat_block_addr8, 2); + } + break; + + case 3: /* Complete */ + if (scb->enable & 1) { + scsi->scb_state = 1; + scsi->scb_addr = scb->scb_chain_addr; + spock_log("Next SCB - %08x\n", scsi->scb_addr); + } else { + spock_set_irq(scsi, scsi->scb_id, IRQ_TYPE_SCB_COMPLETE); + scsi->scb_state = 0; + spock_log("Complete SCB\n"); + } + break; + } + } while (scsi->scb_state != old_scb_state); +} + +static void +spock_process_scsi(spock_t *scsi, scb_t *scb) +{ + int c; + double p; + scsi_device_t *sd; + + switch (scsi->scsi_state) { + case SCSI_STATE_IDLE: + break; + + case SCSI_STATE_SELECT: + if ((scsi->cdb_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[scsi->cdb_id])) { + scsi->scsi_state = SCSI_STATE_SEND_COMMAND; + spock_log("Device selected at ID %i\n", scsi->cdb_id); + break; + } else { + spock_log("Device selection failed at ID %i\n", scsi->cdb_id); + scsi->scsi_state = SCSI_STATE_SELECT_FAILED; + if (!scsi->cmd_timer) { + spock_log("Callback to reset\n"); + scsi->cmd_timer = 1; + } + spock_add_to_period(scsi, 1); + } + break; + + case SCSI_STATE_SELECT_FAILED: + break; + + case SCSI_STATE_SEND_COMMAND: + sd = &scsi_devices[scsi->cdb_id]; + memset(scsi->temp_cdb, 0x00, 12); + + if (scsi->cdb_len < 12) { + memcpy(scsi->temp_cdb, scsi->cdb, + scsi->cdb_len); + spock_add_to_period(scsi, scsi->cdb_len); + } else { + memcpy(scsi->temp_cdb, scsi->cdb, + 12); + spock_add_to_period(scsi, 12); + } + + scsi->data_ptr = scb->sge.sys_buf_addr; + scsi->data_len = scb->sge.sys_buf_byte_count; + + sd->buffer_length = spock_get_len(scsi, scb); + + scsi_device_command_phase0(sd, scsi->temp_cdb); + spock_log("SCSI ID %i: Command %02X: CDB1 = %02x, LUN = %i, Buffer Length %i, SCSI Phase %02X\n", scsi->cdb_id, scsi->temp_cdb[0], scsi->temp_cdb[1], scsi->dev_id[scsi->scb_id].lun_id, sd->buffer_length, sd->phase); + + if (sd->phase != SCSI_PHASE_STATUS && sd->buffer_length > 0) { + p = scsi_device_get_callback(sd); + if (p <= 0.0) + spock_add_to_period(scsi, sd->buffer_length); + else + scsi->media_period += p; + + if (scb->enable & ENABLE_PT) { + int32_t buflen = sd->buffer_length; + int sg_pos = 0; + uint32_t DataTx = 0; + uint32_t Address; + + if (scb->sge.sys_buf_byte_count > 0) { + for (c = 0; c < scsi->data_len; c += 8) { + spock_rd_sge(scsi, scsi->data_ptr + c, &scb->sge); + + Address = scb->sge.sys_buf_addr; + DataTx = MIN((int) scb->sge.sys_buf_byte_count, buflen); + + if ((sd->phase == SCSI_PHASE_DATA_IN) && DataTx) { + spock_log("Writing S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); + DMAPageWrite(Address, &sd->sc->temp_buffer[sg_pos], DataTx); + } else if ((sd->phase == SCSI_PHASE_DATA_OUT) && DataTx) { + spock_log("Reading S/G segment %i: length %i, pointer %08X\n", c, DataTx, Address); + DMAPageRead(Address, &sd->sc->temp_buffer[sg_pos], DataTx); + } + + sg_pos += scb->sge.sys_buf_byte_count; + buflen -= scb->sge.sys_buf_byte_count; + + if (buflen < 0) + buflen = 0; + } + } + } else { + if (sd->phase == SCSI_PHASE_DATA_IN) { + DMAPageWrite(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int)scsi->data_len)); + } else if (sd->phase == SCSI_PHASE_DATA_OUT) + DMAPageRead(scsi->data_ptr, sd->sc->temp_buffer, MIN(sd->buffer_length, (int)scsi->data_len)); + } + + scsi_device_command_phase1(sd); + } + scsi->last_status = sd->status; + scsi->scsi_state = SCSI_STATE_END_PHASE; + break; + + case SCSI_STATE_END_PHASE: + scsi->scsi_state = SCSI_STATE_IDLE; + + spock_log("State to idle\n"); + if (!scsi->cmd_timer) { + scsi->cmd_timer = 1; + } + spock_add_to_period(scsi, 1); + break; + } +} + +static void +spock_callback(void *priv) +{ + double period; + spock_t *scsi = (spock_t *)priv; + scb_t *scb = &scsi->scb; + + scsi->temp_period = 0; + scsi->media_period = 0.0; + + if (scsi->cmd_timer) { + scsi->cmd_timer--; + if (!scsi->cmd_timer) { + spock_execute_cmd(scsi, scb); + } + } + + if (scsi->attention_wait && + (scsi->scb_state == 0 || (scsi->attention_pending & 0xf0) == 0xe0)) { + scsi->attention_wait--; + if (!scsi->attention_wait) { + scsi->attention = scsi->attention_pending; + scsi->status &= ~STATUS_BUSY; + scsi->cir[0] = scsi->cir_pending[0]; + scsi->cir[1] = scsi->cir_pending[1]; + scsi->cir[2] = scsi->cir_pending[2]; + scsi->cir[3] = scsi->cir_pending[3]; + scsi->cir_status = 0; + + switch (scsi->attention >> 4) { + case 1: /*Immediate command*/ + scsi->cmd_status = 0x0a; + scsi->command = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); + switch (scsi->command & CMD_MASK) { + case CMD_ASSIGN: + case CMD_DMA_PACING_CONTROL: + case CMD_FEATURE_CONTROL: + case CMD_INVALID_412: + case CMD_RESET: + spock_process_imm_cmd(scsi); + break; + } + break; + + case 3: case 4: case 0x0f: /*Start SCB*/ + scsi->cmd_status = 1; + scsi->scb_addr = scsi->cir[0] | (scsi->cir[1] << 8) | (scsi->cir[2] << 16) | (scsi->cir[3] << 24); + scsi->scb_id = scsi->attention & 0x0f; + scsi->cmd_timer = SPOCK_TIME * 2; + spock_log("Start SCB at %08x\n", scsi->scb_addr); + scsi->scb_state = 1; + break; + + case 5: /*Invalid*/ + case 0x0a: /*Invalid*/ + scsi->in_invalid = 1; + scsi->cmd_timer = SPOCK_TIME * 2; + break; + + case 0x0e: /*EOI*/ + scsi->irq_status = 0; + spock_clear_irq(scsi, scsi->attention & 0xf); + break; + } + } + } + + spock_process_scsi(scsi, scb); + + period = 0.2 * ((double) scsi->temp_period); + timer_on(&scsi->callback_timer, (scsi->media_period + period + 10.0), 0); + spock_log("Temporary period: %lf us (%" PRIi64 " periods)\n", scsi->callback_timer.period, scsi->temp_period); +} + +static void +spock_mca_write(int port, uint8_t val, void *priv) +{ + spock_t *scsi = (spock_t *)priv; + + if (port < 0x102) + return; + + spock_log("spock_mca_write: port=%04x val=%02x %04x:%04x\n", port, val, CS, cpu_state.pc); + + io_removehandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + mem_mapping_disable(&scsi->bios_rom.mapping); + + scsi->pos_regs[port & 7] = val; + + spock_log("SCSI pos reg write POS2 = %02x, POS3 = %02x, POS4 = %02x\n", scsi->pos_regs[2], scsi->pos_regs[3], scsi->pos_regs[4]); + + if (scsi->pos_regs[2] & 1) { + spock_log("spock scsi io = %04x\n", (((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540); + io_sethandler((((scsi->pos_regs[2] >> 1) & 7) * 8) + 0x3540, 0x0008, spock_read, spock_readw, NULL, spock_write, spock_writew, NULL, scsi); + if ((scsi->pos_regs[2] >> 4) == 0x0f) + mem_mapping_disable(&scsi->bios_rom.mapping); + else { + spock_log("Spock BIOS segment select (hex val) = %02x, enabled bios area is %s\n", scsi->pos_regs[2] >> 4, (scsi->pos_regs[4] & 0x80) ? "32KB" : "16KB"); + mem_mapping_set_addr(&scsi->bios_rom.mapping, ((scsi->pos_regs[2] >> 4) * 0x2000) + 0xc0000, 0x8000); + } + } +} + +static uint8_t +spock_mca_read(int port, void *priv) +{ + spock_t *scsi = (spock_t *)priv; + + spock_log("spock_mca_read: port=%04x %02x %04x:%04x\n", port, scsi->pos_regs[port & 7], CS,cpu_state.pc); + + return scsi->pos_regs[port & 7]; +} + +static uint8_t +spock_mca_feedb(void *priv) +{ + spock_t *scsi = (spock_t *)priv; + + return (scsi->pos_regs[2] & 0x01); +} + +static void +spock_mca_reset(void *priv) +{ + spock_t *scsi = (spock_t *)priv; + int i; + + scsi->in_reset = 2; + scsi->cmd_timer = SPOCK_TIME * 50; + scsi->status = STATUS_BUSY; + scsi->scsi_state = SCSI_STATE_IDLE; + scsi->scb_state = 0; + scsi->in_invalid = 0; + scsi->attention_wait = 0; + scsi->basic_ctrl = 0; + + /* Reset all devices on controller reset. */ + for (i = 0; i < 7; i++) + scsi_device_reset(&scsi_devices[i]); +} + +static void * +spock_init(const device_t *info) +{ + int c; + spock_t *scsi = malloc(sizeof(spock_t)); + memset(scsi, 0x00, sizeof(spock_t)); + + scsi->irq = 14; + + scsi->bios_ver = device_get_config_int("bios_ver"); + + if (scsi->bios_ver) + rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1991_ROM, SPOCK_U69_1991_ROM, + 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); + else + rom_init_interleaved(&scsi->bios_rom, SPOCK_U68_1990_ROM, SPOCK_U69_1990_ROM, + 0xc8000, 0x8000, 0x7fff, 0x4000, MEM_MAPPING_EXTERNAL); + + mem_mapping_disable(&scsi->bios_rom.mapping); + + scsi->pos_regs[0] = 0xff; + scsi->pos_regs[1] = 0x8e; + // mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi); + mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, scsi); + + scsi->in_reset = 2; + scsi->cmd_timer = SPOCK_TIME * 50; + scsi->status = STATUS_BUSY; + + for (c = 0; c < (SCSI_ID_MAX-1); c++) + scsi->dev_id[c].phys_id = -1; + + scsi->dev_id[SCSI_ID_MAX-1].phys_id = 7; + + timer_add(&scsi->callback_timer, spock_callback, scsi, 1); + scsi->callback_timer.period = 10.0; + timer_set_delay_u64(&scsi->callback_timer, (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + return scsi; +} + +static void +spock_close(void *p) +{ + spock_t *scsi = (spock_t *)p; + + if (scsi) { + free(scsi); + scsi = NULL; + } +} + +static int +spock_available(void) +{ + return rom_present(SPOCK_U68_1991_ROM) && rom_present(SPOCK_U69_1991_ROM) && + rom_present(SPOCK_U68_1990_ROM) && rom_present(SPOCK_U69_1990_ROM); +} + +static const device_config_t spock_rom_config[] = { + { + "bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, + { + { + "1991 BIOS (>1GB)", 1 + }, + { + "1990 BIOS", 0 + }, + { + "" + } + }, + }, + { + "", "", -1 + } +}; + +const device_t spock_device = +{ + "IBM PS/2 SCSI Adapter (Spock)", + DEVICE_MCA, + 0, + spock_init, spock_close, NULL, + spock_available, + NULL, NULL, + spock_rom_config +}; diff --git a/src/sound/snd_wss.h b/src/scsi/scsi_spock.h similarity index 57% rename from src/sound/snd_wss.h rename to src/scsi/scsi_spock.h index 77fc9f08c..bf064421c 100644 --- a/src/sound/snd_wss.h +++ b/src/scsi/scsi_spock.h @@ -6,20 +6,20 @@ * * This file is part of the 86Box distribution. * - * Windows Sound System emulation. + * Implementation of the IBM PS/2 SCSI controller with + * cache for MCA only. * - * Version: @(#)snd_wss.c 1.0.0 2018/08/11 + * Version: @(#)scsi_spock.h 1.0.0 2020/03/10 * * Authors: Sarah Walker, * TheCollector1995, * - * Copyright 2012-2018 Sarah Walker. - * Copyright 2018 TheCollector1995. + * Copyright 2020 Sarah Walker. + * Copyright 2020 TheCollector1995. */ -#ifndef SND_WSS_H -# define SND_WSS_H - -extern const device_t wss_device; -extern const device_t ncr_business_audio_device; +#ifndef SCSI_SPOCK_H +# define SCSI_SPOCK_H -#endif /*SND_WSS_H*/ +extern const device_t spock_device; + +#endif /*SCSI_SPOCK_H*/ \ No newline at end of file diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index cd4edbf79..f41d013a0 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -28,18 +28,18 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../dma.h" -#include "../pic.h" -#include "../pci.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "pci.h" +#include "mca.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "nvr.h" +#include "plat.h" #include "scsi.h" #include "scsi_device.h" #include "scsi_aha154x.h" @@ -260,6 +260,11 @@ x54x_bios_scsi_command(scsi_device_t *dev, uint8_t *cdb, uint8_t *buf, int len, return(completion_code(scsi_device_sense(dev))); if (len > 0) { + if (dev->buffer_length == -1) { + fatal("Buffer length -1 when doing SCSI DMA\n"); + return(0xff); + } + if (dev->phase == SCSI_PHASE_DATA_IN) { if (buf) memcpy(buf, dev->sc->temp_buffer, dev->buffer_length); @@ -410,7 +415,7 @@ x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) x54x_log("BIOS Command = 0x%02X\n", cmd->command); - if ((cmd->id > max_id) || (cmd->lun > 7)) { + if (cmd->id > max_id) { x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", cmd->id, cmd->lun); ret = 0x80; @@ -1091,14 +1096,6 @@ x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) return; } - if (req->CmdBlock.common.ControlByte > 0x03) { - x54x_log("Invalid control byte: %02X\n", - req->CmdBlock.common.ControlByte); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, MBI_ERROR); - dev->callback_sub_phase = 4; - return; - } - dev->callback_sub_phase = 1; } } diff --git a/src/serial.c b/src/serial.c index 51297a64b..7d35466a7 100644 --- a/src/serial.c +++ b/src/serial.c @@ -10,15 +10,15 @@ * * Now passes all the AMIDIAG tests. * - * Version: @(#)serial.h 1.0.13 2019/10/31 + * Version: @(#)serial.h 1.0.14 2020/01/24 * * Author: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -30,8 +30,8 @@ #include "86box.h" #include "device.h" #include "timer.h" -#include "machine/machine.h" -#include "io.h" +#include "machine.h" +#include "86box_io.h" #include "pic.h" #include "mem.h" #include "rom.h" @@ -95,7 +95,7 @@ serial_transmit_period(serial_t *dev) ddlab = (double) dev->dlab; /* Bit period based on DLAB. */ - dev->transmit_period = (16000000.0 * ddlab) / 1843200.0; + dev->transmit_period = (16000000.0 * ddlab) / dev->clock_src; } @@ -337,6 +337,16 @@ serial_reset_fifo(serial_t *dev) } +void +serial_set_clock_src(serial_t *dev, double clock_src) +{ + dev->clock_src = clock_src; + + serial_transmit_period(dev); + serial_update_speed(dev); +} + + void serial_write(uint16_t addr, uint8_t val, void *p) { @@ -676,6 +686,7 @@ serial_init(const device_t *info) /* Default to 1200,N,7. */ dev->dlab = 96; dev->fcr = 0x06; + dev->clock_src = 1843200.0; serial_transmit_period(dev); timer_add(&dev->transmit_timer, serial_transmit_timer, dev, 0); timer_add(&dev->timeout_timer, serial_timeout_timer, dev, 0); diff --git a/src/serial.h b/src/serial.h index 73238c87b..7ec03dc66 100644 --- a/src/serial.h +++ b/src/serial.h @@ -8,15 +8,15 @@ * * Definitions for the NS8250/16450/16550 UART emulation. * - * Version: @(#)serial.h 1.0.12 2019/10/31 + * Version: @(#)serial.h 1.0.13 2020/01/24 * * Author: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_SERIAL_H # define EMU_SERIAL_H @@ -53,7 +53,7 @@ typedef struct serial_s rcvr_fifo[16], xmit_fifo[16]; pc_timer_t transmit_timer, timeout_timer; - double transmit_period; + double clock_src, transmit_period; struct serial_device_s *sd; } serial_t; @@ -78,6 +78,7 @@ extern void serial_clear_fifo(serial_t *dev); extern void serial_write_fifo(serial_t *dev, uint8_t dat); extern void serial_set_next_inst(int ni); extern void serial_standalone_init(void); +extern void serial_set_clock_src(serial_t *dev, double clock_src); extern const device_t i8250_device; extern const device_t i8250_pcjr_device; diff --git a/src/sio.h b/src/sio.h index 76f3a08f1..6009545ee 100644 --- a/src/sio.h +++ b/src/sio.h @@ -8,10 +8,10 @@ * * Definitions for the Super I/O chips. * - * Version: @(#)sio.h 1.0.6 2019/05/17 + * Version: @(#)sio.h 1.0.7 2020/01/25 * * Author: Fred N. van Kempen, - * Copyright 2017 Fred N. van Kempen. + * Copyright 2017-2020 Fred N. van Kempen. */ #ifndef EMU_SIO_H # define EMU_SIO_H @@ -28,9 +28,14 @@ extern const device_t fdc37c935_device; extern const device_t pc87306_device; extern const device_t sio_detect_device; extern const device_t um8669f_device; +extern const device_t w83787f_device; extern const device_t w83877f_device; extern const device_t w83877f_president_device; extern const device_t w83877tf_device; +extern const device_t w83877tf_acorp_device; +extern const device_t w83977f_device; +extern const device_t w83977tf_device; +extern const device_t w83977ef_device; #endif /*EMU_SIO_H*/ diff --git a/src/sio_acc3221.c b/src/sio_acc3221.c index 18f759f17..93de9cb0a 100644 --- a/src/sio_acc3221.c +++ b/src/sio_acc3221.c @@ -20,16 +20,16 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "device.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" typedef struct acc3221_t diff --git a/src/sio_detect.c b/src/sio_detect.c index bc0a3e377..189ef3caf 100644 --- a/src/sio_detect.c +++ b/src/sio_detect.c @@ -21,10 +21,10 @@ #include #include "86box.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" diff --git a/src/sio_fdc37c669.c b/src/sio_fdc37c669.c index 1f484af41..1bee36e59 100644 --- a/src/sio_fdc37c669.c +++ b/src/sio_fdc37c669.c @@ -19,16 +19,16 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "device.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" diff --git a/src/sio_fdc37c66x.c b/src/sio_fdc37c66x.c index c1560f920..78d49c991 100644 --- a/src/sio_fdc37c66x.c +++ b/src/sio_fdc37c66x.c @@ -23,16 +23,16 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "device.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" diff --git a/src/sio_fdc37c67x.c b/src/sio_fdc37c67x.c new file mode 100644 index 000000000..3560f8fde --- /dev/null +++ b/src/sio_fdc37c67x.c @@ -0,0 +1,519 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Winbond W83977F Super I/O Chip. + * + * Winbond W83977F Super I/O Chip + * Used by the Award 430TX + * + * Version: @(#)sio_w83977f.c 1.0.0 2020/01/24 + * + * Author: Miran Grca, + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "timer.h" +#include "pci.h" +#include "mem.h" +#include "rom.h" +#include "lpt.h" +#include "serial.h" +#include "fdd.h" +#include "fdc.h" +#include "sio.h" + + +#define HEFRAS (dev->regs[0x26] & 0x40) + + +typedef struct { + uint8_t tries, regs[48], + dev_regs[256][208]; + int locked, rw_locked, + cur_reg, base_address, + type; + fdc_t *fdc; + serial_t *uart[2]; +} w83977f_t; + + +static void w83977f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83977f_read(uint16_t port, void *priv); + + +static void +w83977f_remap(w83977f_t *dev) +{ + io_removehandler(0x3f0, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + io_removehandler(0x370, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + + dev->base_address = (HEFRAS ? 0x370 : 0x3f0); + + io_sethandler(dev->base_address, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); +} + + +static uint8_t +get_lpt_length(w83977f_t *dev) +{ + uint8_t length = 4; + + if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && + ((dev->dev_regs[1][0xc0] & 0x07) != 0x04)) + length = 8; + + return length; +} + + +static void +w83977f_fdc_handler(w83977f_t *dev) +{ + uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31]; + + fdc_remove(dev->fdc); + + pclog("fdc: %02X %02X %04X\n", dev->dev_regs[0][0x00], dev->regs[0x22], io_base); + if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8)) + fdc_set_base(dev->fdc, io_base); + + fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f); +} + + +static void +w83977f_lpt_handler(w83977f_t *dev) +{ + uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31]; + int io_len = get_lpt_length(dev); + io_base &= (0xfff & ~io_len); + io_mask = 0xffc; + if (io_len == 8) + io_mask = 0xff8; + + lpt1_remove(); + + if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) + lpt1_init(io_base); + + lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); +} + + +static void +w83977f_serial_handler(w83977f_t *dev, int uart) +{ + uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31]; + double clock_src = 24000000.0 / 13.0; + + serial_remove(dev->uart[uart]); + + if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8)) + serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f); + + switch (dev->dev_regs[2 + uart][0xc0] & 0x03) { + case 0x00: + clock_src = 24000000.0 / 13.0; + break; + case 0x01: + clock_src = 24000000.0 / 12.0; + break; + case 0x02: + clock_src = 24000000.0 / 1.0; + break; + case 0x03: + clock_src = 24000000.0 / 1.625; + break; + } + + serial_set_clock_src(dev->uart[uart], clock_src); +} + + +static void +w83977f_write(uint16_t port, uint8_t val, void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0; + uint8_t ld = dev->regs[7]; + + // pclog("W83977F Write: %04X %02X\n", port, val); + + if (index) { + if ((val == 0x87) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) + dev->locked = 0; + else + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; + } else { + if (dev->locked) { + if (dev->rw_locked) + return; + if (dev->cur_reg >= 0x30) { + valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30]; + dev->dev_regs[ld][dev->cur_reg - 0x30] = val; + } else { + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } + } else + return; + } + + switch (dev->cur_reg) { + case 0x02: + if (valxor & 0x02) + softresetx86(); + break; + case 0x22: + if (valxor & 0x20) + w83977f_serial_handler(dev, 1); + if (valxor & 0x10) + w83977f_serial_handler(dev, 0); + if (valxor & 0x08) + w83977f_lpt_handler(dev); + if (valxor & 0x01) + w83977f_fdc_handler(dev); + break; + case 0x26: + if (valxor & 0x20) + dev->rw_locked = (val & 0x20) ? 1 : 0; + case 0x30: + if (valxor & 0x01) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0x60: case 0x61: + if (valxor & 0xff) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0x70: + if (valxor & 0x0f) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0xf0: + switch (ld) { + case 0x00: + if (valxor & 0x20) + fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); + break; + case 0x01: + if (valxor & 0x07) + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + if (valxor & 0x03) + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0xf1: + switch (ld) { + case 0x00: + if (valxor & 0xc0) + fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); + if (valxor & 0x0c) + fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); + if (valxor & 0x02) + fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); + if (valxor & 0x01) + fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); + break; + } + break; + case 0xf2: + switch (ld) { + case 0x00: + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, val & 0x03); + break; + } + break; + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + switch (ld) { + case 0x00: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); + break; + } + break; + } +} + + +static uint8_t +w83977f_read(uint16_t port, void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + uint8_t ret = 0xff; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ld = dev->regs[7]; + + if (dev->locked) { + if (index) + ret = dev->cur_reg; + else { + if (!dev->rw_locked) { + if ((dev->cur_reg == 0xf2) && (ld == 0x00)) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + else if (dev->cur_reg >= 0x30) + ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; + else + ret = dev->regs[dev->cur_reg]; + } + } + } + + // pclog("W83977F Read: %04X %02X\n", port, ret); + + return ret; +} + + +static void +w83977f_reset(w83977f_t *dev) +{ + int i; + + memset(dev->regs, 0, 48); + for (i = 0; i < 256; i++) + memset(dev->dev_regs[i], 0, 208); + + dev->regs[0x20] = 0x97; + dev->regs[0x21] = dev->type ? 0x73 : 0x71; + dev->regs[0x22] = 0xff; + dev->regs[0x24] = dev->type ? 0x84 : 0xa4; + + /* WARNING: Array elements are register - 0x30. */ + /* Logical Device 0 (FDC) */ + dev->dev_regs[0][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[0][0x01] = 0x02; + dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0; + dev->dev_regs[0][0x40] = 0x06; + if (!dev->type) + dev->dev_regs[0][0x41] = 0x02; /* Read-only */ + dev->dev_regs[0][0x44] = 0x02; + dev->dev_regs[0][0xc0] = 0x0e; + + /* Logical Device 1 (Parallel Port) */ + dev->dev_regs[1][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[1][0x01] = 0x02; + dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78; + dev->dev_regs[1][0x40] = 0x07; + if (!dev->type) + dev->dev_regs[1][0x41] = 0x02; /* Read-only */ + dev->dev_regs[1][0x44] = 0x04; + dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is priner mode. */ + + /* Logical Device 2 (UART A) */ + dev->dev_regs[2][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[2][0x01] = 0x02; + dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8; + dev->dev_regs[2][0x40] = 0x04; + if (!dev->type) + dev->dev_regs[2][0x41] = 0x02; /* Read-only */ + + /* Logical Device 3 (UART B) */ + dev->dev_regs[3][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[3][0x01] = 0x02; + dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8; + dev->dev_regs[3][0x40] = 0x03; + if (!dev->type) + dev->dev_regs[3][0x41] = 0x02; /* Read-only */ + + /* Logical Device 4 (RTC) */ + if (!dev->type) { + dev->dev_regs[4][0x00] = 0x01; + dev->dev_regs[4][0x01] = 0x02; + dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70; + dev->dev_regs[4][0x40] = 0x08; + dev->dev_regs[4][0x41] = 0x02; /* Read-only */ + } + + /* Logical Device 5 (KBC) */ + dev->dev_regs[5][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[5][0x01] = 0x02; + dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60; + dev->dev_regs[5][0x40] = 0x01; + if (!dev->type) + dev->dev_regs[5][0x41] = 0x02; /* Read-only */ + dev->dev_regs[5][0x42] = 0x0c; + if (!dev->type) + dev->dev_regs[5][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40; + + /* Logical Device 6 (IR) = UART C */ + if (!dev->type) { + dev->dev_regs[6][0x01] = 0x02; + dev->dev_regs[6][0x41] = 0x02; /* Read-only */ + dev->dev_regs[6][0x44] = 0x04; + dev->dev_regs[6][0x45] = 0x04; + } + + /* Logical Device 7 (Auxiliary I/O Part I) */ + if (!dev->type) + dev->dev_regs[7][0x01] = 0x02; + if (!dev->type) + dev->dev_regs[7][0x41] = 0x02; /* Read-only */ + if (!dev->type) + dev->dev_regs[7][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; + dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; + dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; + dev->dev_regs[7][0xb6] = 0x01; + if (dev->type) + dev->dev_regs[7][0xb7] = 0x01; + + /* Logical Device 8 (Auxiliary I/O Part II) */ + if (!dev->type) + dev->dev_regs[8][0x01] = 0x02; + if (!dev->type) + dev->dev_regs[8][0x41] = 0x02; /* Read-only */ + if (!dev->type) + dev->dev_regs[8][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01; + dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01; + dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01; + dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01; + + /* Logical Device 9 (Auxiliary I/O Part III) */ + if (dev->type) { + dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; + dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; + dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; + dev->dev_regs[7][0xb6] = 0x01; dev->dev_regs[7][0xb7] = 0x01; + } + + fdc_reset(dev->fdc); + + serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + + w83977f_fdc_handler(dev); + w83977f_lpt_handler(dev); + w83977f_serial_handler(dev, 0); + w83977f_serial_handler(dev, 1); + + w83977f_remap(dev); + + dev->locked = 0; + dev->rw_locked = 0; +} + + +static void +w83977f_close(void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + + free(dev); +} + + +static void * +w83977f_init(const device_t *info) +{ + w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t)); + memset(dev, 0, sizeof(w83977f_t)); + + dev->type = info->local; + + dev->fdc = device_add(&fdc_at_smc_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + w83977f_reset(dev); + + return dev; +} + + +const device_t w83977f_device = { + "Winbond W83977F Super I/O", + 0, + 0, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +const device_t w83977tf_device = { + "Winbond W83977TF Super I/O", + 0, + 1, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/sio_fdc37c93x.c b/src/sio_fdc37c93x.c index e93ffea54..f34bc7e8e 100644 --- a/src/sio_fdc37c93x.c +++ b/src/sio_fdc37c93x.c @@ -20,16 +20,16 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "device.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" @@ -203,7 +203,7 @@ static void fdc37c93x_gpio_handler(fdc37c93x_t *dev) break; } dev->gpio_base = ld_port; - if ((ld_port >= 0x0100) && (ld_port <= 0x0FFE)) + if (ld_port > 0x0000) io_sethandler(dev->gpio_base, 0x0002, fdc37c93x_gpio_read, NULL, NULL, fdc37c93x_gpio_write, NULL, NULL, dev); } diff --git a/src/sio_pc87306.c b/src/sio_pc87306.c index c2d3ceaf8..7b9a733b6 100644 --- a/src/sio_pc87306.c +++ b/src/sio_pc87306.c @@ -19,18 +19,19 @@ #include #include #include "86box.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "device.h" #include "lpt.h" #include "mem.h" +#include "nvr.h" #include "pci.h" #include "rom.h" #include "serial.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" @@ -40,6 +41,7 @@ typedef struct { int cur_reg; fdc_t *fdc; serial_t *uart[2]; + nvr_t *nvr; } pc87306_t; @@ -287,6 +289,14 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) } } break; + case 4: + // pclog("NVR RAM mask set to %i\n", !!(val & 0x80)); + break; + case 5: + // pclog("Reserved set to %i\n", !!(val & 0x04)); + // pclog("RTC is now %sabled\n", (val & 0x08) ? "en" : "dis"); + // pclog("NVR RAM bank set to %i\n", !!(val & 0x20)); + break; case 9: if (valxor & 0x44) { fdc_update_enh_mode(dev->fdc, (val & 4) ? 1 : 0); @@ -298,6 +308,7 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) pc87306_gpio_init(dev); break; case 0x12: + // pclog("NVR RAM 38-3F lock set to %i\n", !!(val & 0x01)); if (valxor & 0x30) pc87306_gpio_init(dev); break; @@ -406,6 +417,8 @@ pc87306_init(const device_t *info) dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); + // dev->nvr = device_add(&piix4_nvr_device); + pc87306_reset(dev); io_sethandler(0x02e, 0x0002, diff --git a/src/sio_um8669f.c b/src/sio_um8669f.c index d946c251c..0d7b21511 100644 --- a/src/sio_um8669f.c +++ b/src/sio_um8669f.c @@ -28,13 +28,13 @@ PnP registers : #include #include "86box.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "pci.h" #include "lpt.h" #include "serial.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" @@ -181,7 +181,8 @@ um8669f_pnp_read(uint16_t port, void *priv) } -void um8669f_write(uint16_t port, uint8_t val, void *priv) +void +um8669f_write(uint16_t port, uint8_t val, void *priv) { um8669f_t *dev = (um8669f_t *) priv; int new_pnp_active; @@ -224,7 +225,8 @@ void um8669f_write(uint16_t port, uint8_t val, void *priv) } -uint8_t um8669f_read(uint16_t port, void *priv) +uint8_t +um8669f_read(uint16_t port, void *priv) { um8669f_t *dev = (um8669f_t *) priv; uint8_t ret = 0xff; @@ -297,7 +299,7 @@ um8669f_init(const device_t *info) um8669f_t *dev = (um8669f_t *) malloc(sizeof(um8669f_t)); memset(dev, 0, sizeof(um8669f_t)); - dev->fdc = device_add(&fdc_at_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); diff --git a/src/sio_w83787f.c b/src/sio_w83787f.c new file mode 100644 index 000000000..df77b5062 --- /dev/null +++ b/src/sio_w83787f.c @@ -0,0 +1,387 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Winbond W83787F/IF Super I/O Chip. + * + * Winbond W83787F Super I/O Chip + * Used by the Award 430HX + * + * Version: @(#)sio_w83787f.c 1.0.0 2020/01/11 + * + * Author: Miran Grca, + * Copyright 2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "timer.h" +#include "pci.h" +#include "mem.h" +#include "rom.h" +#include "lpt.h" +#include "serial.h" +#include "fdd.h" +#include "fdc.h" +#include "sio.h" + + +#define FDDA_TYPE (dev->regs[7] & 3) +#define FDDB_TYPE ((dev->regs[7] >> 2) & 3) +#define FDDC_TYPE ((dev->regs[7] >> 4) & 3) +#define FDDD_TYPE ((dev->regs[7] >> 6) & 3) + +#define FD_BOOT (dev->regs[8] & 3) +#define SWWP ((dev->regs[8] >> 4) & 1) +#define DISFDDWR ((dev->regs[8] >> 5) & 1) + +#define EN3MODE ((dev->regs[9] >> 5) & 1) + +#define DRV2EN_NEG (dev->regs[0xB] & 1) /* 0 = drive 2 installed */ +#define INVERTZ ((dev->regs[0xB] >> 1) & 1) /* 0 = invert DENSEL polarity */ +#define IDENT ((dev->regs[0xB] >> 3) & 1) + +#define HEFERE ((dev->regs[0xC] >> 5) & 1) + + +typedef struct { + uint8_t tries, regs[42]; + uint16_t reg_init; + int locked, rw_locked, + cur_reg, + key; + fdc_t *fdc; + serial_t *uart[2]; +} w83787f_t; + + +static void w83787f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83787f_read(uint16_t port, void *priv); + + +static void +w83787f_remap(w83787f_t *dev) +{ + io_removehandler(0x250, 0x0003, + w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); + io_sethandler(0x250, 0x0003, + w83787f_read, NULL, NULL, w83787f_write, NULL, NULL, dev); + dev->key = 0x88 | HEFERE; +} + + +#ifdef FIXME +/* FIXME: Implement EPP (and ECP) parallel port modes. */ +static uint8_t +get_lpt_length(w83787f_t *dev) +{ + uint8_t length = 4; + + if (dev->regs[9] & 0x80) { + if (dev->regs[0] & 0x04) + length = 8; /* EPP mode. */ + if (dev->regs[0] & 0x08) + length |= 0x80; /* ECP mode. */ + } + + return length; +} +#endif + + +static void +w83787f_serial_handler(w83787f_t *dev, int uart) +{ + int urs0 = !!(dev->regs[1] & (1 << uart)); + int urs1 = !!(dev->regs[1] & (4 << uart)); + int urs2 = !!(dev->regs[3] & (8 >> uart)); + int urs, irq = 4; + uint16_t addr = 0x3f8, enable = 1; + + urs = (urs1 << 1) | urs0; + + if (urs2) { + addr = uart ? 0x3f8 : 0x2f8; + irq = uart ? 4 : 3; + } else { + switch (urs) { + case 0: + addr = uart ? 0x3e8 : 0x2e8; + irq = uart ? 4 : 3; + break; + case 1: + addr = uart ? 0x2e8 : 0x3e8; + irq = uart ? 3 : 4; + break; + case 2: + addr = uart ? 0x2f8 : 0x3f8; + irq = uart ? 3 : 4; + break; + case 3: + default: + enable = 0; + break; + } + } + + if (dev->regs[4] & (0x20 >> uart)) + enable = 0; + + serial_remove(dev->uart[uart]); + if (enable) + serial_setup(dev->uart[uart], addr, irq); +} + + +static void +w83787f_lpt_handler(w83787f_t *dev) +{ + int ptrs0 = !!(dev->regs[1] & 4); + int ptrs1 = !!(dev->regs[1] & 5); + int ptrs, irq = 7; + uint16_t addr = 0x378, enable = 1; + + ptrs = (ptrs1 << 1) | ptrs0; + + switch (ptrs) { + case 0: + addr = 0x3bc; + irq = 7; + break; + case 1: + addr = 0x278; + irq = 5; + break; + case 2: + addr = 0x378; + irq = 7; + break; + case 3: + default: + enable = 0; + break; + } + + if (dev->regs[4] & 0x80) + enable = 0; + + lpt1_remove(); + if (enable) { + lpt1_init(addr); + lpt1_irq(irq); + } +} + + +static void +w83787f_fdc_handler(w83787f_t *dev) +{ + fdc_remove(dev->fdc); + if (!(dev->regs[0] & 0x20)) + fdc_set_base(dev->fdc, (dev->regs[0] & 0x10) ? 0x03f0 : 0x0370); +} + + +static void +w83787f_write(uint16_t port, uint8_t val, void *priv) +{ + w83787f_t *dev = (w83787f_t *) priv; + uint8_t valxor = 0; + uint8_t max = 0x15; + pclog("W83787F: Write %02X to %04X\n", val, port); + + if (port == 0x250) { + if (val == dev->key) + dev->locked = 1; + else + dev->locked = 0; + return; + } else if (port == 0x251) { + if (val <= max) + dev->cur_reg = val; + return; + } else { + if (dev->locked) { + if (dev->rw_locked) + return; + if (dev->cur_reg == 6) + val &= 0xF3; + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } else + return; + } + + switch (dev->cur_reg) { + case 0: + if (valxor & 0x30) + w83787f_fdc_handler(dev); + if (valxor & 0x0c) + w83787f_lpt_handler(dev); + break; + case 1: + if (valxor & 0x80) + fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); + if (valxor & 0x30) + w83787f_lpt_handler(dev); + if (valxor & 0x0a) + w83787f_serial_handler(dev, 1); + if (valxor & 0x05) + w83787f_serial_handler(dev, 0); + break; + case 3: + if (valxor & 0x80) + w83787f_lpt_handler(dev); + if (valxor & 0x08) + w83787f_serial_handler(dev, 0); + if (valxor & 0x04) + w83787f_serial_handler(dev, 1); + break; + case 4: + if (valxor & 0x10) + w83787f_serial_handler(dev, 1); + if (valxor & 0x20) + w83787f_serial_handler(dev, 0); + if (valxor & 0x80) + w83787f_lpt_handler(dev); + break; + case 6: + if (valxor & 0x08) { + fdc_remove(dev->fdc); + if (!(dev->regs[6] & 0x08)) + fdc_set_base(dev->fdc, 0x03f0); + } + break; + case 7: + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, FDDA_TYPE); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, FDDB_TYPE); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, FDDC_TYPE); + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, FDDD_TYPE); + break; + case 8: + if (valxor & 0x03) + fdc_update_boot_drive(dev->fdc, FD_BOOT); + if (valxor & 0x10) + fdc_set_swwp(dev->fdc, SWWP ? 1 : 0); + if (valxor & 0x20) + fdc_set_diswr(dev->fdc, DISFDDWR ? 1 : 0); + break; + case 9: + if (valxor & 0x20) + fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); + if (valxor & 0x40) + dev->rw_locked = (val & 0x40) ? 1 : 0; + if (valxor & 0x80) + w83787f_lpt_handler(dev); + break; + case 0xC: + if (valxor & 0x20) + w83787f_remap(dev); + break; + } +} + + +static uint8_t +w83787f_read(uint16_t port, void *priv) +{ + w83787f_t *dev = (w83787f_t *) priv; + uint8_t ret = 0xff; + + if (dev->locked) { + if (port == 0x251) + ret = dev->cur_reg; + else if (port == 0x252) { + if (dev->cur_reg == 7) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); + else if (!dev->rw_locked) + ret = dev->regs[dev->cur_reg]; + } + } + + pclog("W83787F: Read %02X from %04X\n", ret, port); + + return ret; +} + + +static void +w83787f_reset(w83787f_t *dev) +{ + lpt1_remove(); + lpt1_init(0x378); + lpt1_irq(7); + + fdc_reset(dev->fdc); + + memset(dev->regs, 0, 0x2A); + dev->regs[0x00] = 0x50; + dev->regs[0x01] = 0x2C; + dev->regs[0x03] = 0x30; + dev->regs[0x07] = 0xF5; + dev->regs[0x09] = dev->reg_init & 0xff; + dev->regs[0x0a] = 0x1F; + dev->regs[0x0c] = 0x2C; + dev->regs[0x0d] = 0xA3; + + serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + + dev->key = 0x89; + + w83787f_remap(dev); + + dev->locked = 0; + dev->rw_locked = 0; +} + + +static void +w83787f_close(void *priv) +{ + w83787f_t *dev = (w83787f_t *) priv; + + free(dev); +} + + +static void * +w83787f_init(const device_t *info) +{ + w83787f_t *dev = (w83787f_t *) malloc(sizeof(w83787f_t)); + memset(dev, 0, sizeof(w83787f_t)); + + dev->fdc = device_add(&fdc_at_winbond_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + dev->reg_init = info->local; + + w83787f_reset(dev); + + return dev; +} + + +const device_t w83787f_device = { + "Winbond W83787F/IF Super I/O", + 0, + 0x09, + w83787f_init, w83787f_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/sio_w83877f.c b/src/sio_w83877f.c index 69ad67286..c9304e7db 100644 --- a/src/sio_w83877f.c +++ b/src/sio_w83877f.c @@ -11,7 +11,7 @@ * Winbond W83877F Super I/O Chip * Used by the Award 430HX * - * Version: @(#)sio_w83877f.c 1.0.16 2020/01/11 + * Version: @(#)sio_w83877f.c 1.0.17 2020/01/25 * * Author: Miran Grca, * Copyright 2016-2020 Miran Grca. @@ -23,15 +23,15 @@ #include #include "86box.h" #include "device.h" -#include "io.h" +#include "86box_io.h" #include "timer.h" #include "pci.h" #include "mem.h" #include "rom.h" #include "lpt.h" #include "serial.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" +#include "fdd.h" +#include "fdc.h" #include "sio.h" @@ -148,18 +148,65 @@ make_port(w83877f_t *dev, uint8_t reg) } +static void +w83877f_fdc_handler(w83877f_t *dev) +{ + fdc_remove(dev->fdc); + if (!(dev->regs[6] & 0x08) && (dev->regs[0x20] & 0xc0)) + fdc_set_base(dev->fdc, 0x03f0); +} + + +static void +w83877f_lpt_handler(w83877f_t *dev) +{ + uint8_t lpt_irq; + uint8_t lpt_irqs[8] = { 0, 7, 9, 10, 11, 14, 15, 5 }; + + lpt1_remove(); + if (!(dev->regs[4] & 0x80) && (dev->regs[0x23] & 0xc0)) + lpt1_init(make_port(dev, 0x23)); + + lpt_irq = 0xff; + + lpt_irq = lpt_irqs[ECPIRQ]; + if (lpt_irq == 0) + lpt_irq = PRTIQS; + + lpt1_irq(lpt_irq); +} + + static void w83877f_serial_handler(w83877f_t *dev, int uart) { int reg_mask = uart ? 0x10 : 0x20; - int reg_id = uart ? 0x24 : 0x25; + int reg_id = uart ? 0x25 : 0x24; int irq_mask = uart ? 0x0f : 0xf0; - int irq_shift = uart ? 4 : 0; + int irq_shift = uart ? 0 : 4; + double clock_src = 24000000.0 / 13.0; - if ((dev->regs[4] & reg_mask) || !(dev->regs[reg_id] & 0xc0)) - serial_remove(dev->uart[uart]); - else + serial_remove(dev->uart[uart]); + if (!(dev->regs[4] & reg_mask) && (dev->regs[reg_id] & 0xc0)) serial_setup(dev->uart[uart], make_port(dev, reg_id), (dev->regs[0x28] & irq_mask) >> irq_shift); + + switch (!!(dev->regs[0x19] & (0x02 >> uart))) { + case 0: + switch (!!(dev->regs[0x03] & (0x02 >> uart))) { + case 0: + clock_src = 24000000.0 / 13.0; + break; + case 1: + clock_src = 24000000.0 / 12.0; + break; + } + break; + case 1: + clock_src = 14769000.0; + break; + } + + serial_set_clock_src(dev->uart[uart], clock_src); } @@ -169,7 +216,6 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) w83877f_t *dev = (w83877f_t *) priv; uint8_t valxor = 0; uint8_t max = 0x2A; - uint8_t lpt_irq; if (port == 0x250) { if (val == dev->key) @@ -223,33 +269,30 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0: - if (valxor & 0x0c) { - lpt1_remove(); - if (!(dev->regs[4] & 0x80)) - lpt1_init(make_port(dev, 0x23)); - } + if (valxor & 0x0c) + w83877f_lpt_handler(dev); break; case 1: if (valxor & 0x80) fdc_set_swap(dev->fdc, (dev->regs[1] & 0x80) ? 1 : 0); break; + case 3: + if (valxor & 0x02) + w83877f_serial_handler(dev, 0); + if (valxor & 0x01) + w83877f_serial_handler(dev, 1); + break; case 4: if (valxor & 0x10) w83877f_serial_handler(dev, 1); if (valxor & 0x20) w83877f_serial_handler(dev, 0); - if (valxor & 0x80) { - lpt1_remove(); - if (!(dev->regs[4] & 0x80)) - lpt1_init(make_port(dev, 0x23)); - } + if (valxor & 0x80) + w83877f_lpt_handler(dev); break; case 6: - if (valxor & 0x08) { - fdc_remove(dev->fdc); - if (!(dev->regs[6] & 0x08)) - fdc_set_base(dev->fdc, 0x03f0); - } + if (valxor & 0x08) + w83877f_fdc_handler(dev); break; case 7: if (valxor & 0x03) @@ -274,11 +317,8 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) fdc_update_enh_mode(dev->fdc, EN3MODE ? 1 : 0); if (valxor & 0x40) dev->rw_locked = (val & 0x40) ? 1 : 0; - if (valxor & 0x80) { - lpt1_remove(); - if (!(dev->regs[4] & 0x80)) - lpt1_init(make_port(dev, 0x23)); - } + if (valxor & 0x80) + w83877f_lpt_handler(dev); break; case 0xB: if (valxor & 1) @@ -294,19 +334,19 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) if (valxor & 1) w83877f_remap(dev); break; + case 0x19: + if (valxor & 0x02) + w83877f_serial_handler(dev, 0); + if (valxor & 0x01) + w83877f_serial_handler(dev, 1); + break; case 0x20: - if (valxor) { - fdc_remove(dev->fdc); - if (!(dev->regs[4] & 0x80)) - fdc_set_base(dev->fdc, make_port(dev, 0x20)); - } + if (valxor) + w83877f_fdc_handler(dev); break; case 0x23: - if (valxor) { - lpt1_remove(); - if (!(dev->regs[4] & 0x80)) - lpt1_init(make_port(dev, 0x23)); - } + if (valxor) + w83877f_lpt_handler(dev); break; case 0x24: if (valxor & 0xfe) @@ -317,27 +357,19 @@ w83877f_write(uint16_t port, uint8_t val, void *priv) w83877f_serial_handler(dev, 1); break; case 0x27: - if (valxor & 0xef) { - lpt_irq = 0xff; - - if (PRTIQS != 0x00) - lpt_irq = ECPIRQ; - - lpt1_irq(lpt_irq); - } + if (valxor & 0xef) + w83877f_lpt_handler(dev); break; case 0x28: if (valxor & 0xf) { if ((dev->regs[0x28] & 0x0f) == 0) dev->regs[0x28] |= 0x03; - if (!(dev->regs[2] & 0x10)) - serial_setup(dev->uart[1], make_port(dev, 0x25), dev->regs[0x28] & 0x0f); + w83877f_serial_handler(dev, 1); } if (valxor & 0xf0) { if ((dev->regs[0x28] & 0xf0) == 0) dev->regs[0x28] |= 0x40; - if (!(dev->regs[4] & 0x20)) - serial_setup(dev->uart[0], make_port(dev, 0x24), (dev->regs[0x28] & 0xf0) >> 4); + w83877f_serial_handler(dev, 0); } break; } @@ -355,7 +387,7 @@ w83877f_read(uint16_t port, void *priv) ret = dev->cur_reg; else if ((port == 0x3f1) || (port == 0x252)) { if (dev->cur_reg == 7) - ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2)); + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); else if ((dev->cur_reg >= 0x18) || !dev->rw_locked) ret = dev->regs[dev->cur_reg]; } @@ -368,9 +400,6 @@ w83877f_read(uint16_t port, void *priv) static void w83877f_reset(w83877f_t *dev) { - lpt1_remove(); - lpt1_init(0x378); - fdc_reset(dev->fdc); memset(dev->regs, 0, 0x2A); @@ -389,12 +418,16 @@ w83877f_reset(w83877f_t *dev) dev->regs[0x24] = (0x3f8 >> 2) & 0xfe; dev->regs[0x25] = (0x2f8 >> 2) & 0xfe; dev->regs[0x26] = (2 << 4) | 4; - dev->regs[0x27] = (6 << 4) | 7; + dev->regs[0x27] = (2 << 4) | 5; dev->regs[0x28] = (4 << 4) | 3; dev->regs[0x29] = 0x62; - serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); - serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + w83877f_fdc_handler(dev); + + w83877f_lpt_handler(dev); + + w83877f_serial_handler(dev, 0); + w83877f_serial_handler(dev, 1); dev->base_address = 0x3f0; dev->key = 0x89; @@ -463,3 +496,13 @@ const device_t w83877tf_device = { NULL, NULL, NULL, NULL }; + + +const device_t w83877tf_acorp_device = { + "Winbond W83877TF Super I/O", + 0, + 0x0c05, + w83877f_init, w83877f_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/sio_w83977f.c b/src/sio_w83977f.c new file mode 100644 index 000000000..770ce2c7a --- /dev/null +++ b/src/sio_w83977f.c @@ -0,0 +1,535 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Emulation of the Winbond W83977F Super I/O Chip. + * + * Winbond W83977F Super I/O Chip + * Used by the Award 430TX + * + * Version: @(#)sio_w83977f.c 1.0.0 2020/01/24 + * + * Author: Miran Grca, + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "timer.h" +#include "pci.h" +#include "mem.h" +#include "rom.h" +#include "lpt.h" +#include "serial.h" +#include "fdd.h" +#include "fdc.h" +#include "sio.h" + + +#define HEFRAS (dev->regs[0x26] & 0x40) + + +typedef struct { + uint8_t tries, regs[48], + dev_regs[256][208]; + int locked, rw_locked, + cur_reg, base_address, + type; + fdc_t *fdc; + serial_t *uart[2]; +} w83977f_t; + + +static void w83977f_write(uint16_t port, uint8_t val, void *priv); +static uint8_t w83977f_read(uint16_t port, void *priv); + + +static void +w83977f_remap(w83977f_t *dev) +{ + io_removehandler(0x3f0, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + io_removehandler(0x370, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); + + dev->base_address = (HEFRAS ? 0x370 : 0x3f0); + + io_sethandler(dev->base_address, 0x0002, + w83977f_read, NULL, NULL, w83977f_write, NULL, NULL, dev); +} + + +static uint8_t +get_lpt_length(w83977f_t *dev) +{ + uint8_t length = 4; + + if (((dev->dev_regs[1][0xc0] & 0x07) != 0x00) && ((dev->dev_regs[1][0xc0] & 0x07) != 0x02) && + ((dev->dev_regs[1][0xc0] & 0x07) != 0x04)) + length = 8; + + return length; +} + + +static void +w83977f_fdc_handler(w83977f_t *dev) +{ + uint16_t io_base = (dev->dev_regs[0][0x30] << 8) | dev->dev_regs[0][0x31]; + + fdc_remove(dev->fdc); + + if ((dev->dev_regs[0][0x00] & 0x01) && (dev->regs[0x22] & 0x01) && (io_base >= 0x100) && (io_base <= 0xff8)) + fdc_set_base(dev->fdc, io_base); + + fdc_set_irq(dev->fdc, dev->dev_regs[0][0x40] & 0x0f); +} + + +static void +w83977f_lpt_handler(w83977f_t *dev) +{ + uint16_t io_mask, io_base = (dev->dev_regs[1][0x30] << 8) | dev->dev_regs[1][0x31]; + int io_len = get_lpt_length(dev); + io_base &= (0xfff & ~io_len); + io_mask = 0xffc; + if (io_len == 8) + io_mask = 0xff8; + + lpt1_remove(); + + if ((dev->dev_regs[1][0x00] & 0x01) && (dev->regs[0x22] & 0x08) && (io_base >= 0x100) && (io_base <= io_mask)) + lpt1_init(io_base); + + lpt1_irq(dev->dev_regs[1][0x40] & 0x0f); +} + + +static void +w83977f_serial_handler(w83977f_t *dev, int uart) +{ + uint16_t io_base = (dev->dev_regs[2 + uart][0x30] << 8) | dev->dev_regs[2 + uart][0x31]; + double clock_src = 24000000.0 / 13.0; + + serial_remove(dev->uart[uart]); + + if ((dev->dev_regs[2 + uart][0x00] & 0x01) && (dev->regs[0x22] & (0x10 << uart)) && (io_base >= 0x100) && (io_base <= 0xff8)) + serial_setup(dev->uart[uart], io_base, dev->dev_regs[2 + uart][0x40] & 0x0f); + + switch (dev->dev_regs[2 + uart][0xc0] & 0x03) { + case 0x00: + clock_src = 24000000.0 / 13.0; + break; + case 0x01: + clock_src = 24000000.0 / 12.0; + break; + case 0x02: + clock_src = 24000000.0 / 1.0; + break; + case 0x03: + clock_src = 24000000.0 / 1.625; + break; + } + + serial_set_clock_src(dev->uart[uart], clock_src); +} + + +static void +w83977f_write(uint16_t port, uint8_t val, void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t valxor = 0; + uint8_t ld = dev->regs[7]; + + if (index) { + if ((val == 0x87) && !dev->locked) { + if (dev->tries) { + dev->locked = 1; + dev->tries = 0; + } else + dev->tries++; + } else { + if (dev->locked) { + if (val == 0xaa) + dev->locked = 0; + else + dev->cur_reg = val; + } else { + if (dev->tries) + dev->tries = 0; + } + } + return; + } else { + if (dev->locked) { + if (dev->rw_locked) + return; + if (dev->cur_reg >= 0x30) { + valxor = val ^ dev->dev_regs[ld][dev->cur_reg - 0x30]; + dev->dev_regs[ld][dev->cur_reg - 0x30] = val; + } else { + valxor = val ^ dev->regs[dev->cur_reg]; + dev->regs[dev->cur_reg] = val; + } + } else + return; + } + + switch (dev->cur_reg) { + case 0x02: + /* if (valxor & 0x02) + softresetx86(); */ + break; + case 0x22: + if (valxor & 0x20) + w83977f_serial_handler(dev, 1); + if (valxor & 0x10) + w83977f_serial_handler(dev, 0); + if (valxor & 0x08) + w83977f_lpt_handler(dev); + if (valxor & 0x01) + w83977f_fdc_handler(dev); + break; + case 0x26: + if (valxor & 0x40) + w83977f_remap(dev); + if (valxor & 0x20) + dev->rw_locked = (val & 0x20) ? 1 : 0; + break; + case 0x30: + if (valxor & 0x01) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0x60: case 0x61: + if (valxor & 0xff) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0x70: + if (valxor & 0x0f) switch (ld) { + case 0x00: + w83977f_fdc_handler(dev); + break; + case 0x01: + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0xf0: + switch (ld) { + case 0x00: + if (valxor & 0x20) + fdc_update_drv2en(dev->fdc, (val & 0x20) ? 0 : 1); + if (valxor & 0x10) + fdc_set_swap(dev->fdc, (val & 0x10) ? 1 : 0); + if (valxor & 0x01) + fdc_update_enh_mode(dev->fdc, (val & 0x01) ? 1 : 0); + break; + case 0x01: + if (valxor & 0x07) + w83977f_lpt_handler(dev); + break; + case 0x02: case 0x03: + if (valxor & 0x03) + w83977f_serial_handler(dev, ld - 2); + break; + } + break; + case 0xf1: + switch (ld) { + case 0x00: + if (valxor & 0xc0) + fdc_update_boot_drive(dev->fdc, (val & 0xc0) >> 6); + if (valxor & 0x0c) + fdc_update_densel_force(dev->fdc, (val & 0x0c) >> 2); + if (valxor & 0x02) + fdc_set_diswr(dev->fdc, (val & 0x02) ? 1 : 0); + if (valxor & 0x01) + fdc_set_swwp(dev->fdc, (val & 0x01) ? 1 : 0); + break; + } + break; + case 0xf2: + switch (ld) { + case 0x00: + if (valxor & 0xc0) + fdc_update_rwc(dev->fdc, 3, (val & 0xc0) >> 6); + if (valxor & 0x30) + fdc_update_rwc(dev->fdc, 2, (val & 0x30) >> 4); + if (valxor & 0x0c) + fdc_update_rwc(dev->fdc, 1, (val & 0x0c) >> 2); + if (valxor & 0x03) + fdc_update_rwc(dev->fdc, 0, val & 0x03); + break; + } + break; + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + switch (ld) { + case 0x00: + if (valxor & 0x18) + fdc_update_drvrate(dev->fdc, dev->cur_reg & 0x03, (val & 0x18) >> 3); + break; + } + break; + } +} + + +static uint8_t +w83977f_read(uint16_t port, void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + uint8_t ret = 0xff; + uint8_t index = (port & 1) ? 0 : 1; + uint8_t ld = dev->regs[7]; + + if (dev->locked) { + if (index) + ret = dev->cur_reg; + else { + if (!dev->rw_locked) { + if ((dev->cur_reg == 0xf2) && (ld == 0x00)) + ret = (fdc_get_rwc(dev->fdc, 0) | (fdc_get_rwc(dev->fdc, 1) << 2) | (fdc_get_rwc(dev->fdc, 2) << 4) | (fdc_get_rwc(dev->fdc, 3) << 6)); + else if (dev->cur_reg >= 0x30) + ret = dev->dev_regs[ld][dev->cur_reg - 0x30]; + else + ret = dev->regs[dev->cur_reg]; + } + } + } + + return ret; +} + + +static void +w83977f_reset(w83977f_t *dev) +{ + int i; + + memset(dev->regs, 0, 48); + for (i = 0; i < 256; i++) + memset(dev->dev_regs[i], 0, 208); + + if (dev->type < 2) { + dev->regs[0x20] = 0x97; + dev->regs[0x21] = dev->type ? 0x73 : 0x71; + } else { + dev->regs[0x20] = 0x52; + dev->regs[0x21] = 0xf0; + } + dev->regs[0x22] = 0xff; + dev->regs[0x24] = dev->type ? 0x84 : 0xa4; + + /* WARNING: Array elements are register - 0x30. */ + /* Logical Device 0 (FDC) */ + dev->dev_regs[0][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[0][0x01] = 0x02; + dev->dev_regs[0][0x30] = 0x03; dev->dev_regs[0][0x31] = 0xf0; + dev->dev_regs[0][0x40] = 0x06; + if (!dev->type) + dev->dev_regs[0][0x41] = 0x02; /* Read-only */ + dev->dev_regs[0][0x44] = 0x02; + dev->dev_regs[0][0xc0] = 0x0e; + + /* Logical Device 1 (Parallel Port) */ + dev->dev_regs[1][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[1][0x01] = 0x02; + dev->dev_regs[1][0x30] = 0x03; dev->dev_regs[1][0x31] = 0x78; + dev->dev_regs[1][0x40] = 0x07; + if (!dev->type) + dev->dev_regs[1][0x41] = 0x01 /*0x02*/; /* Read-only */ + dev->dev_regs[1][0x44] = 0x04; + dev->dev_regs[1][0xc0] = 0x3c; /* The datasheet says default is 3f, but also default is printer mode. */ + + /* Logical Device 2 (UART A) */ + dev->dev_regs[2][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[2][0x01] = 0x02; + dev->dev_regs[2][0x30] = 0x03; dev->dev_regs[2][0x31] = 0xf8; + dev->dev_regs[2][0x40] = 0x04; + if (!dev->type) + dev->dev_regs[2][0x41] = 0x02; /* Read-only */ + + /* Logical Device 3 (UART B) */ + dev->dev_regs[3][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[3][0x01] = 0x02; + dev->dev_regs[3][0x30] = 0x02; dev->dev_regs[3][0x31] = 0xf8; + dev->dev_regs[3][0x40] = 0x03; + if (!dev->type) + dev->dev_regs[3][0x41] = 0x02; /* Read-only */ + + /* Logical Device 4 (RTC) */ + if (!dev->type) { + dev->dev_regs[4][0x00] = 0x01; + dev->dev_regs[4][0x01] = 0x02; + dev->dev_regs[4][0x30] = 0x00; dev->dev_regs[4][0x31] = 0x70; + dev->dev_regs[4][0x40] = 0x08; + dev->dev_regs[4][0x41] = 0x02; /* Read-only */ + } + + /* Logical Device 5 (KBC) */ + dev->dev_regs[5][0x00] = 0x01; + if (!dev->type) + dev->dev_regs[5][0x01] = 0x02; + dev->dev_regs[5][0x30] = 0x00; dev->dev_regs[5][0x31] = 0x60; + dev->dev_regs[5][0x32] = 0x00; dev->dev_regs[5][0x33] = 0x64; + dev->dev_regs[5][0x40] = 0x01; + if (!dev->type) + dev->dev_regs[5][0x41] = 0x02; /* Read-only */ + dev->dev_regs[5][0x42] = 0x0c; + if (!dev->type) + dev->dev_regs[5][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[5][0xc0] = dev->type ? 0x83 : 0x40; + + /* Logical Device 6 (IR) = UART C */ + if (!dev->type) { + dev->dev_regs[6][0x01] = 0x02; + dev->dev_regs[6][0x41] = 0x02; /* Read-only */ + dev->dev_regs[6][0x44] = 0x04; + dev->dev_regs[6][0x45] = 0x04; + } + + /* Logical Device 7 (Auxiliary I/O Part I) */ + if (!dev->type) + dev->dev_regs[7][0x01] = 0x02; + if (!dev->type) + dev->dev_regs[7][0x41] = 0x02; /* Read-only */ + if (!dev->type) + dev->dev_regs[7][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[7][0xb0] = 0x01; dev->dev_regs[7][0xb1] = 0x01; + dev->dev_regs[7][0xb2] = 0x01; dev->dev_regs[7][0xb3] = 0x01; + dev->dev_regs[7][0xb4] = 0x01; dev->dev_regs[7][0xb5] = 0x01; + dev->dev_regs[7][0xb6] = 0x01; + if (dev->type) + dev->dev_regs[7][0xb7] = 0x01; + + /* Logical Device 8 (Auxiliary I/O Part II) */ + if (!dev->type) + dev->dev_regs[8][0x01] = 0x02; + if (!dev->type) + dev->dev_regs[8][0x41] = 0x02; /* Read-only */ + if (!dev->type) + dev->dev_regs[8][0x43] = 0x02; /* Read-only? */ + dev->dev_regs[8][0xb8] = 0x01; dev->dev_regs[8][0xb9] = 0x01; + dev->dev_regs[8][0xba] = 0x01; dev->dev_regs[8][0xbb] = 0x01; + dev->dev_regs[8][0xbc] = 0x01; dev->dev_regs[8][0xbd] = 0x01; + dev->dev_regs[8][0xbe] = 0x01; dev->dev_regs[8][0xbf] = 0x01; + + /* Logical Device 9 (Auxiliary I/O Part III) */ + if (dev->type) { + dev->dev_regs[9][0xb0] = 0x01; dev->dev_regs[9][0xb1] = 0x01; + dev->dev_regs[9][0xb2] = 0x01; dev->dev_regs[9][0xb3] = 0x01; + dev->dev_regs[9][0xb4] = 0x01; dev->dev_regs[9][0xb5] = 0x01; + dev->dev_regs[9][0xb6] = 0x01; dev->dev_regs[9][0xb7] = 0x01; + + dev->dev_regs[10][0xc0] = 0x8f; + } + + fdc_reset(dev->fdc); + + serial_setup(dev->uart[0], SERIAL1_ADDR, SERIAL1_IRQ); + serial_setup(dev->uart[1], SERIAL2_ADDR, SERIAL2_IRQ); + + w83977f_fdc_handler(dev); + w83977f_lpt_handler(dev); + w83977f_serial_handler(dev, 0); + w83977f_serial_handler(dev, 1); + + w83977f_remap(dev); + + dev->locked = 0; + dev->rw_locked = 0; +} + + +static void +w83977f_close(void *priv) +{ + w83977f_t *dev = (w83977f_t *) priv; + + free(dev); +} + + +static void * +w83977f_init(const device_t *info) +{ + w83977f_t *dev = (w83977f_t *) malloc(sizeof(w83977f_t)); + memset(dev, 0, sizeof(w83977f_t)); + + dev->type = info->local; + + dev->fdc = device_add(&fdc_at_smc_device); + + dev->uart[0] = device_add_inst(&ns16550_device, 1); + dev->uart[1] = device_add_inst(&ns16550_device, 2); + + w83977f_reset(dev); + + return dev; +} + + +const device_t w83977f_device = { + "Winbond W83977F Super I/O", + 0, + 0, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +const device_t w83977tf_device = { + "Winbond W83977TF Super I/O", + 0, + 1, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; + + +const device_t w83977ef_device = { + "Winbond W83977TF Super I/O", + 0, + 2, + w83977f_init, w83977f_close, NULL, + NULL, NULL, NULL, + NULL +}; diff --git a/src/smbus.c b/src/smbus.c new file mode 100644 index 000000000..171d4fad5 --- /dev/null +++ b/src/smbus.c @@ -0,0 +1,410 @@ +/* + * 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. + * + * Implement SMBus (System Management Bus) and its operations. + * + * Version: @(#)smbus.c 1.0.0 2020/03/21 + * + * Authors: RichardG, + * + * Copyright 2020 RichardG. + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "smbus.h" + + +#define NADDRS 128 /* SMBus supports 128 addresses */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + + +typedef struct _smbus_ { + uint8_t (*read_byte)(uint8_t addr, void *priv); + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv); + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv); + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv); + + void (*write_byte)(uint8_t addr, uint8_t val, void *priv); + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv); + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv); + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv); + + void *priv; + + struct _smbus_ *prev, *next; +} smbus_t; + +int smbus_initialized = 0; +smbus_t *smbus[NADDRS], *smbus_last[NADDRS]; + +#define ENABLE_SMBUS_LOG 1 +#ifdef ENABLE_SMBUS_LOG +int smbus_do_log = ENABLE_SMBUS_LOG; + + +static void +smbus_log(const char *fmt, ...) +{ + va_list ap; + + if (smbus_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +#define smbus_log(fmt, ...) +#endif + + +#ifdef ENABLE_SMBUS_LOG +static uint8_t smbus_null_read_byte(uint8_t addr, void *priv) { smbus_log("SMBus: read_byte(%02x)\n", addr); return(0xff); } +static uint8_t smbus_null_read_byte_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_byte_cmd(%02x, %02x)\n", addr, cmd); return(0xff); } +static uint16_t smbus_null_read_word_cmd(uint8_t addr, uint8_t cmd, void *priv) { smbus_log("SMBus: read_word_cmd(%02x, %02x)\n", addr, cmd); return(0xffff); } +static uint8_t smbus_null_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv) { smbus_log("SMBus: read_block_cmd(%02x, %02x)\n", addr, cmd); return(0x00); }; +static void smbus_null_write_byte(uint8_t addr, uint8_t val, void *priv) { smbus_log("SMBus: write_byte(%02x, %02x)\n", addr, val); } +static void smbus_null_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val, void *priv) { smbus_log("SMBus: write_byte_cmd(%02x, %02x, %02x)\n", addr, cmd, val); } +static void smbus_null_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val, void *priv) { smbus_log("SMBus: write_word_cmd(%02x, %02x, %04x)\n", addr, cmd, val); } +static void smbus_null_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv) { smbus_log("SMBus: write_block_cmd(%02x, %02x, %02x)\n", addr, cmd, len); } +#endif + + +void +smbus_init(void) +{ + int c; + smbus_t *p, *q; + + if (!smbus_initialized) { + for (c=0; cprev; + free(p); + p = q; + } + p = NULL; + } + +#ifdef ENABLE_SMBUS_LOG + /* smbus[c] should be the only handler, pointing at the NULL catch handler. */ + p = (smbus_t *) malloc(sizeof(smbus_t)); + memset(p, 0, sizeof(smbus_t)); + smbus[c] = smbus_last[c] = p; + p->next = NULL; + p->prev = NULL; + p->read_byte = smbus_null_read_byte; + p->read_byte_cmd = smbus_null_read_byte_cmd; + p->read_word_cmd = smbus_null_read_word_cmd; + p->read_block_cmd = smbus_null_read_block_cmd; + p->write_byte = smbus_null_write_byte; + p->write_byte_cmd = smbus_null_write_byte_cmd; + p->write_word_cmd = smbus_null_write_word_cmd; + p->write_block_cmd = smbus_null_write_block_cmd; + p->priv = NULL; +#else + /* smbus[c] should be NULL. */ + smbus[c] = smbus_last[c] = NULL; +#endif + } +} + + +void +smbus_sethandler(uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + int c; + smbus_t *p, *q = NULL; + + for (c = 0; c < size; c++) { + p = smbus_last[base + c]; + q = (smbus_t *) malloc(sizeof(smbus_t)); + memset(q, 0, sizeof(smbus_t)); + if (p) { + p->next = q; + q->prev = p; + } else { + smbus[base + c] = q; + q->prev = NULL; + } + + q->read_byte = read_byte; + q->read_byte_cmd = read_byte_cmd; + q->read_word_cmd = read_word_cmd; + q->read_block_cmd = read_block_cmd; + + q->write_byte = write_byte; + q->write_byte_cmd = write_byte_cmd; + q->write_word_cmd = write_word_cmd; + q->write_block_cmd = write_block_cmd; + + q->priv = priv; + q->next = NULL; + + smbus_last[base + c] = q; + } +} + + +void +smbus_removehandler(uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + int c; + smbus_t *p; + + for (c = 0; c < size; c++) { + p = smbus[base + c]; + if (!p) + continue; + while(p) { + if ((p->read_byte == read_byte) && (p->read_byte_cmd == read_byte_cmd) && + (p->read_word_cmd == read_word_cmd) && (p->read_block_cmd == read_block_cmd) && + (p->write_byte == write_byte) && (p->write_byte_cmd == write_byte_cmd) && + (p->write_word_cmd == write_word_cmd) && (p->write_block_cmd == write_block_cmd) && + (p->priv == priv)) { + if (p->prev) + p->prev->next = p->next; + else + smbus[base + c] = p->next; + if (p->next) + p->next->prev = p->prev; + else + smbus_last[base + c] = p->prev; + free(p); + p = NULL; + break; + } + p = p->next; + } + } +} + + +void +smbus_handler(int set, uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv) +{ + if (set) + smbus_sethandler(base, size, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv); + else + smbus_removehandler(base, size, read_byte, read_byte_cmd, read_word_cmd, read_block_cmd, write_byte, write_byte_cmd, write_word_cmd, write_block_cmd, priv); +} + + +uint8_t +smbus_has_device(uint8_t addr) +{ + return(!!smbus[addr]); +} + + +uint8_t +smbus_read_byte(uint8_t addr) +{ + uint8_t ret = 0xff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_byte) { + ret &= p->read_byte(addr, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint8_t +smbus_read_byte_cmd(uint8_t addr, uint8_t cmd) +{ + uint8_t ret = 0xff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_byte_cmd) { + ret &= p->read_byte_cmd(addr, cmd, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint16_t +smbus_read_word_cmd(uint8_t addr, uint8_t cmd) +{ + uint16_t ret = 0xffff; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_word_cmd) { + ret &= p->read_word_cmd(addr, cmd, p->priv); + found++; + } + p = p->next; + } + } + + return(ret); +} + +uint8_t +smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data) +{ + uint8_t ret = 0; + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->read_block_cmd) { + ret = MAX(ret, p->read_block_cmd(addr, cmd, data, p->priv)); + found++; + } + p = p->next; + } + } + + return(ret); +} + + +void +smbus_write_byte(uint8_t addr, uint8_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_byte) { + p->write_byte(addr, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_byte_cmd) { + p->write_byte_cmd(addr, cmd, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val) +{ + smbus_t *p; + int found = 0; + + if (smbus[addr]) { + p = smbus[addr]; + while(p) { + if (p->write_word_cmd) { + p->write_word_cmd(addr, cmd, val, p->priv); + found++; + } + p = p->next; + } + } + + return; +} + +void +smbus_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len) +{ + smbus_t *p; + int found = 0; + + p = smbus[addr]; + if (p) { + while(p) { + if (p->write_block_cmd) { + p->write_block_cmd(addr, cmd, data, len, p->priv); + found++; + } + p = p->next; + } + } + + return; +} diff --git a/src/smbus.h b/src/smbus.h new file mode 100644 index 000000000..a4fec4a5c --- /dev/null +++ b/src/smbus.h @@ -0,0 +1,67 @@ +/* + * 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. + * + * Definitions for the SMBus handler. + * + * Version: @(#)smbus.h 1.0.0 2020/03/21 + * + * Authors: RichardG, + * + * Copyright 2020 RichardG. + */ +#ifndef EMU_SMBUS_H +# define EMU_SMBUS_H + + +extern void smbus_init(void); + +extern void smbus_sethandler(uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +extern void smbus_removehandler(uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +extern void smbus_handler(int set, uint8_t base, int size, + uint8_t (*read_byte)(uint8_t addr, void *priv), + uint8_t (*read_byte_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint16_t (*read_word_cmd)(uint8_t addr, uint8_t cmd, void *priv), + uint8_t (*read_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, void *priv), + void (*write_byte)(uint8_t addr, uint8_t val, void *priv), + void (*write_byte_cmd)(uint8_t addr, uint8_t cmd, uint8_t val, void *priv), + void (*write_word_cmd)(uint8_t addr, uint8_t cmd, uint16_t val, void *priv), + void (*write_block_cmd)(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len, void *priv), + void *priv); + +extern uint8_t smbus_has_device(uint8_t addr); +extern uint8_t smbus_read_byte(uint8_t addr); +extern uint8_t smbus_read_byte_cmd(uint8_t addr, uint8_t cmd); +extern uint16_t smbus_read_word_cmd(uint8_t addr, uint8_t cmd); +extern uint8_t smbus_read_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data); +extern void smbus_write_byte(uint8_t addr, uint8_t val); +extern void smbus_write_byte_cmd(uint8_t addr, uint8_t cmd, uint8_t val); +extern void smbus_write_word_cmd(uint8_t addr, uint8_t cmd, uint16_t val); +extern void smbus_write_block_cmd(uint8_t addr, uint8_t cmd, uint8_t *data, uint8_t len); + + +#endif /*EMU_SMBUS_H*/ diff --git a/src/sound/midi.c b/src/sound/midi.c index 31a8b86bf..3c7da9966 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -8,35 +8,28 @@ * * MIDI device core module. * - * Version: @(#)midi.c 1.0.2 2018/12/31 + * Version: @(#)midi.c 1.0.3 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * Bit, * DOSBox Team, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2016-2018 Bit. - * Copyright 2008-2018 DOSBox Team. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Bit. + * Copyright 2008-2020 DOSBox Team. */ #include #include #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_midi.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "plat_midi.h" #include "midi.h" -#include "midi_system.h" -#ifdef USE_FLUIDSYNTH -# include "midi_fluidsynth.h" -#endif -#ifdef USE_MUNT -# include "midi_mt32.h" -#endif #include "midi_input.h" @@ -47,9 +40,8 @@ static int midi_input_device_last = 0; midi_t *midi = NULL, *midi_in = NULL; -void (*input_msg)(void *p, uint8_t *msg); -int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); -void *midi_in_p; +midi_in_handler_t *mih_first = NULL, *mih_last = NULL, + *mih_cur = NULL; uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; @@ -227,7 +219,7 @@ void play_msg(uint8_t *msg) { if (midi->m_out_device->play_msg) - midi->m_out_device->play_msg(msg); + midi->m_out_device->play_msg(msg); } @@ -235,7 +227,7 @@ void play_sysex(uint8_t *sysex, unsigned int len) { if (midi->m_out_device->play_sysex) - midi->m_out_device->play_sysex(sysex, len); + midi->m_out_device->play_sysex(sysex, len); } @@ -290,6 +282,7 @@ midi_in_device_get_from_internal_name(char *s) return 0; } + void midi_in_device_init() { @@ -298,39 +291,40 @@ midi_in_device_init() midi_input_device_last = midi_input_device_current; } + void midi_raw_out_rt_byte(uint8_t val) { - if (!midi_in->midi_realtime) - return; - - if ((!midi_in->midi_clockout && (val == 0xf8))) + if (!midi_in->midi_realtime) return; - midi_in->midi_cmd_r = val << 24; - pclog("Play RT Byte msg\n"); - play_msg((uint8_t *)&midi_in->midi_cmd_r); + if ((!midi_in->midi_clockout && (val == 0xf8))) + return; + + midi_in->midi_cmd_r = val << 24; + /* pclog("Play RT Byte msg\n"); */ + play_msg((uint8_t *)&midi_in->midi_cmd_r); } + void midi_raw_out_thru_rt_byte(uint8_t val) { - if (midi_in->thruchan) - midi_raw_out_rt_byte(val); + if (midi_in->thruchan) + midi_raw_out_rt_byte(val); } + void midi_raw_out_byte(uint8_t val) { uint32_t passed_ticks; - if (!midi || !midi->m_out_device) { + if (!midi || !midi->m_out_device) return; - } - if ((midi->m_out_device->write && midi->m_out_device->write(val))) { + if ((midi->m_out_device->write && midi->m_out_device->write(val))) return; - } if (midi->midi_sysex_start) { passed_ticks = plat_get_ticks() - midi->midi_sysex_start; @@ -396,12 +390,223 @@ midi_raw_out_byte(uint8_t val) } } + void midi_clear_buffer(void) { - if (!midi) return; - midi->midi_pos = 0; - midi->midi_status = 0x00; - midi->midi_cmd_pos = 0; - midi->midi_cmd_len = 0; -} \ No newline at end of file + if (!midi) + return; + + midi->midi_pos = 0; + midi->midi_status = 0x00; + midi->midi_cmd_pos = 0; + midi->midi_cmd_len = 0; +} + + +void +midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p) +{ + midi_in_handler_t *temp = NULL, *next; + + if (set) { + /* Add MIDI IN handler. */ + if ((mih_first == NULL) && (mih_last != NULL)) + fatal("Last MIDI IN handler present with no first MIDI IN handler\n"); + + if ((mih_first != NULL) && (mih_last == NULL)) + fatal("First MIDI IN handler present with no last MIDI IN handler\n"); + + temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t)); + memset(temp, 0, sizeof(midi_in_handler_t)); + temp->msg = msg; + temp->sysex = sysex; + temp->p = p; + + if (mih_last == NULL) + mih_first = mih_last = temp; + else { + temp->prev = mih_last; + mih_last = temp; + } + } else if ((mih_first != NULL) && (mih_last != NULL)) { + temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) { + if (temp->prev != NULL) + temp->prev->next = temp->next; + + if (temp->next != NULL) + temp->next->prev = temp->prev; + + next = temp->next; + + if (temp == mih_first) { + mih_first = NULL; + if (next == NULL) + mih_last = NULL; + } + + if (temp == mih_last) + mih_last = NULL; + + free(temp); + temp = next; + + if (next == NULL) + break; + } + } + } +} + + +void +midi_in_handlers_clear(void) +{ + midi_in_handler_t *temp = mih_first, *next; + + while(1) { + if (temp == NULL) + break; + + next = temp->next; + free(temp); + + temp = next; + + if (next == NULL) + break; + } + + mih_first = mih_last = NULL; +} + + +void +midi_in_msg(uint8_t *msg) +{ + midi_in_handler_t *temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + if (temp->msg) + temp->msg(temp->p, msg); + + temp = temp->next; + + if (temp == NULL) + break; + } +} + + +static void +midi_start_sysex(uint8_t *buffer, uint32_t len) +{ + midi_in_handler_t *temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + temp->cnt = 5; + temp->buf = buffer; + temp->len = len; + + temp = temp->next; + + if (temp == NULL) + break; + } +} + + +/* Returns: + 0 = All handlers have returnd 0; + 1 = There are still handlers to go. */ +static int +midi_do_sysex(void) +{ + midi_in_handler_t *temp = mih_first; + int ret, cnt_acc = 0; + + while(1) { + if (temp == NULL) + break; + + /* Do nothing if the handler has a zero count. */ + if ((temp->cnt > 0) || (temp->len > 0)) { + ret = 0; + if (temp->sysex) { + if (temp->cnt == 0) + ret = temp->sysex(temp->p, temp->buf, 0, 0); + else + ret = temp->sysex(temp->p, temp->buf, temp->len, 0); + } + + /* If count is 0 and length is 0, then this is just a finishing + call to temp->sysex(), so skip this entire block. */ + if (temp->cnt > 0) { + if (ret) { + /* Decrease or reset the counter. */ + if (temp->len == ret) + temp->cnt--; + else + temp->cnt = 5; + + /* Advance the buffer pointer and remember the + remaining length. */ + temp->buf += (temp->len - ret); + temp->len = ret; + } else { + /* Set count to 0 so that this handler will be + ignored on the next interation. */ + temp->cnt = 0; + + /* Reset the buffer pointer and length. */ + temp->buf = NULL; + temp->len = 0; + } + + /* If the remaining count is above zero, add it to the + accumulator. */ + if (temp->cnt > 0) + cnt_acc |= temp->cnt; + } + } + + temp = temp->next; + + if (temp == NULL) + break; + } + + /* Return 0 if all handlers have returned 0 or all the counts are otherwise 0. */ + if (cnt_acc == 0) + return 0; + else + return 1; +} + + +void +midi_in_sysex(uint8_t *buffer, uint32_t len) +{ + midi_start_sysex(buffer, len); + + while (1) { + /* This will return 0 if all theh handlers have either + timed out or otherwise indicated it is time to stop. */ + if (midi_do_sysex()) + plat_delay_ms(5); /* msec */ + else + break; + } +} diff --git a/src/sound/midi.h b/src/sound/midi.h index 8e516c2a3..a41f369da 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -11,7 +11,7 @@ extern int midi_device_current; extern int midi_input_device_current; extern void (*input_msg)(void *p, uint8_t *msg); -extern int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); +extern int (*input_sysex)(void *p, uint8_t *buf, uint32_t len, int abort); extern void *midi_in_p; int midi_device_available(int card); @@ -34,12 +34,24 @@ void midi_in_device_init(); typedef struct midi_device_t { - void (*play_sysex)(uint8_t *sysex, unsigned int len); - void (*play_msg)(uint8_t *msg); - void (*poll)(); - int (*write)(uint8_t val); + void (*play_sysex)(uint8_t *sysex, unsigned int len); + void (*play_msg)(uint8_t *msg); + void (*poll)(); + int (*write)(uint8_t val); } midi_device_t; +typedef struct midi_in_handler_t +{ + uint8_t *buf; + int cnt; + uint32_t len; + + void (*msg)(void *p, uint8_t *msg); + int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); + struct midi_in_handler_t *p; + struct midi_in_handler_t *prev, *next; +} midi_in_handler_t; + typedef struct midi_t { uint8_t midi_rt_buf[8], midi_cmd_buf[8], @@ -53,15 +65,20 @@ typedef struct midi_t extern midi_t *midi, *midi_in; -void midi_init(midi_device_t* device); -void midi_in_init(midi_device_t* device, midi_t **mididev); -void midi_close(); -void midi_in_close(void); -void midi_raw_out_rt_byte(uint8_t val); -void midi_raw_out_thru_rt_byte(uint8_t val); -void midi_raw_out_byte(uint8_t val); -void midi_clear_buffer(void); -void midi_poll(); +extern void midi_init(midi_device_t* device); +extern void midi_in_init(midi_device_t* device, midi_t **mididev); +extern void midi_close(); +extern void midi_in_close(void); +extern void midi_raw_out_rt_byte(uint8_t val); +extern void midi_raw_out_thru_rt_byte(uint8_t val); +extern void midi_raw_out_byte(uint8_t val); +extern void midi_clear_buffer(void); +extern void midi_poll(); + +extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p); +extern void midi_in_handlers_clear(void); +extern void midi_in_msg(uint8_t *msg); +extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #if 0 #ifdef _WIN32 @@ -79,4 +96,15 @@ void midi_poll(); #define MIDI_INPUT_NAME "MIDI Input Device" #define MIDI_INPUT_INTERNAL_NAME "midi_in" +#ifdef EMU_DEVICE_H +extern const device_t system_midi_device; +#ifdef USE_FLUIDSYNTH +extern const device_t fluidsynth_device; +#endif +#ifdef USE_MUNT +extern const device_t mt32_device; +extern const device_t cm32l_device; +#endif +#endif + #endif /*EMU_SOUND_MIDI_H*/ diff --git a/src/sound/midi_fluidsynth.c b/src/sound/midi_fluidsynth.c index 822213d11..6a3f42c08 100644 --- a/src/sound/midi_fluidsynth.c +++ b/src/sound/midi_fluidsynth.c @@ -5,14 +5,13 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../ui.h" +#include "86box.h" +#include "config.h" +#include "device.h" +#include "plat.h" +#include "plat_dynld.h" +#include "ui.h" #include "midi.h" -#include "midi_fluidsynth.h" #include "sound.h" diff --git a/src/sound/midi_fluidsynth.h b/src/sound/midi_fluidsynth.h deleted file mode 100644 index 518b1461d..000000000 --- a/src/sound/midi_fluidsynth.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t fluidsynth_device; diff --git a/src/sound/midi_mt32.c b/src/sound/midi_mt32.c index c62d98da2..1d6707d11 100644 --- a/src/sound/midi_mt32.c +++ b/src/sound/midi_mt32.c @@ -4,14 +4,13 @@ #include #include #include "munt/c_interface/c_interface.h" -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../rom.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "rom.h" +#include "plat.h" #include "sound.h" #include "midi.h" -#include "midi_mt32.h" extern void givealbuffer_midi(void *buf, uint32_t size); diff --git a/src/sound/midi_mt32.h b/src/sound/midi_mt32.h deleted file mode 100644 index 0aa012fa1..000000000 --- a/src/sound/midi_mt32.h +++ /dev/null @@ -1,2 +0,0 @@ -extern const device_t mt32_device; -extern const device_t cm32l_device; diff --git a/src/sound/midi_system.c b/src/sound/midi_system.c index 6ee56b01a..90c9bc36e 100644 --- a/src/sound/midi_system.c +++ b/src/sound/midi_system.c @@ -3,12 +3,11 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_midi.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "plat_midi.h" #include "midi.h" -#include "midi_system.h" #include "midi_input.h" diff --git a/src/sound/openal.c b/src/sound/openal.c index 185730a57..ad0d5f957 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -29,7 +29,7 @@ # include # include # include -#include "../86box.h" +#include "86box.h" #include "sound.h" #include "midi.h" diff --git a/src/sound/snd_ad1848.c b/src/sound/snd_ad1848.c index fd5631b12..f8681ff86 100644 --- a/src/sound/snd_ad1848.c +++ b/src/sound/snd_ad1848.c @@ -7,10 +7,10 @@ #include #include #include -#include "../86box.h" -#include "../dma.h" -#include "../pic.h" -#include "../timer.h" +#include "86box.h" +#include "dma.h" +#include "pic.h" +#include "timer.h" #include "sound.h" #include "snd_ad1848.h" diff --git a/src/sound/snd_ad1848.h b/src/sound/snd_ad1848.h index 6ec719475..0778cdfec 100644 --- a/src/sound/snd_ad1848.h +++ b/src/sound/snd_ad1848.h @@ -18,7 +18,7 @@ typedef struct ad1848_t int freq; pc_timer_t timer_count; - uint64_t timer_latch; + uint64_t timer_latch; int16_t buffer[SOUNDBUFLEN * 2]; int pos; diff --git a/src/sound/snd_adlib.c b/src/sound/snd_adlib.c index c0417f69d..29ace4e49 100644 --- a/src/sound/snd_adlib.c +++ b/src/sound/snd_adlib.c @@ -5,13 +5,12 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mca.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mca.h" +#include "device.h" #include "sound.h" -#include "snd_adlib.h" #include "snd_opl.h" diff --git a/src/sound/snd_adlib.h b/src/sound/snd_adlib.h deleted file mode 100644 index 4a6a161ca..000000000 --- a/src/sound/snd_adlib.h +++ /dev/null @@ -1,2 +0,0 @@ -extern const device_t adlib_device; -extern const device_t adlib_mca_device; diff --git a/src/sound/snd_adlibgold.c b/src/sound/snd_adlibgold.c index 06a4fcee5..c45f85b41 100644 --- a/src/sound/snd_adlibgold.c +++ b/src/sound/snd_adlibgold.c @@ -3,13 +3,13 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../dma.h" -#include "../pic.h" -#include "../device.h" -#include "../nvr.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "dma.h" +#include "pic.h" +#include "device.h" +#include "nvr.h" #include "sound.h" #include "filters.h" #include "snd_opl.h" @@ -20,11 +20,11 @@ typedef struct adgold_t { int adgold_irq_status; - uint8_t adgold_eeprom[0x19]; + uint8_t adgold_eeprom[0x1a]; uint8_t adgold_status; int adgold_38x_state, adgold_38x_addr; - uint8_t adgold_38x_regs[0x19]; + uint8_t adgold_38x_regs[0x1a]; int adgold_mma_addr; uint8_t adgold_mma_regs[2][0xe]; @@ -211,9 +211,9 @@ void adgold_write(uint16_t addr, uint8_t val, void *p) { case 0x00: /*Control/ID*/ if (val & 1) - memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x19); + memcpy(adgold->adgold_38x_regs, adgold->adgold_eeprom, 0x1a); if (val & 2) - memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x19); + memcpy(adgold->adgold_eeprom, adgold->adgold_38x_regs, 0x1a); break; case 0x04: /*Final output volume left*/ @@ -384,7 +384,7 @@ void adgold_write(uint16_t addr, uint8_t val, void *p) adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val; break; case 7: - if (adgold->adgold_mma_addr >= 0xf) break; + if (adgold->adgold_mma_addr >= 0xe) break; switch (adgold->adgold_mma_addr) { case 0x9: @@ -503,8 +503,10 @@ uint8_t adgold_read(uint16_t addr, void *p) } break; case 7: - if (adgold->adgold_mma_addr >= 0xf) temp = 0xff; - temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; + if (adgold->adgold_mma_addr >= 0xf) + temp = 0xff; + else + temp = adgold->adgold_mma_regs[1][adgold->adgold_mma_addr]; break; } return temp; @@ -774,7 +776,8 @@ void *adgold_init(const device_t *info) f = nvr_fopen(L"adgold.bin", L"rb"); if (f) { - fread(adgold->adgold_eeprom, 0x18, 1, f); + if (fread(adgold->adgold_eeprom, 1, 0x1a, f) != 0x1a) + fatal("adgold_init(): Error reading data\n"); fclose(f); } diff --git a/src/sound/snd_adlibgold.h b/src/sound/snd_adlibgold.h deleted file mode 100644 index daea1b490..000000000 --- a/src/sound/snd_adlibgold.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t adgold_device; diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index f24a383d3..5e87c993d 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -5,17 +5,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../nmi.h" -#include "../mem.h" -#include "../pci.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "nmi.h" +#include "mem.h" +#include "pci.h" +#include "timer.h" #include "sound.h" #include "midi.h" #include "snd_mpu401.h" -#include "snd_audiopci.h" #define N 16 @@ -25,7 +24,7 @@ static float low_fir_es1371_coef[ES1371_NCoef]; typedef struct { - mpu_t mpu; + mpu_t mpu; uint8_t pci_command, pci_serr; @@ -84,6 +83,8 @@ typedef struct { int pos; int16_t buffer[SOUNDBUFLEN * 2]; + + int type; } es1371_t; @@ -130,10 +131,13 @@ typedef struct { #define INT_STATUS_DAC1 (1<<2) #define INT_STATUS_DAC2 (1<<1) +#define UART_CTRL_RXINTEN (1<<7) #define UART_CTRL_TXINTEN (1<<5) +#define UART_STATUS_RXINT (1<<7) #define UART_STATUS_TXINT (1<<2) #define UART_STATUS_TXRDY (1<<1) +#define UART_STATUS_RXRDY (1<<0) #define FORMAT_MONO_8 0 #define FORMAT_STEREO_8 1 @@ -875,40 +879,43 @@ static uint8_t es1371_pci_read(int func, int addr, void *p) //audiopci_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc); + if (addr > 0x3f) + return 0x00; + switch (addr) { case 0x00: return 0x74; /*Ensoniq*/ case 0x01: return 0x12; - case 0x02: return 0x71; /*ES1371*/ + case 0x02: return 0x71; /* ES1371 */ case 0x03: return 0x13; - + case 0x04: return es1371->pci_command; case 0x05: return es1371->pci_serr; - case 0x06: return 0x10; /*Supports ACPI*/ - case 0x07: return 0; + case 0x06: return 0x10; /* Supports support ACPI */ + case 0x07: return 0x00; - case 0x08: return 2; /*Revision ID*/ - case 0x09: return 0x00; /*Multimedia audio device*/ + case 0x08: return 0x02; /* Revision ID */ + case 0x09: return 0x00; /* Multimedia audio device */ case 0x0a: return 0x01; case 0x0b: return 0x04; - case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /*memBaseAddr*/ + case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /* memBaseAddr */ case 0x11: return es1371->base_addr >> 8; case 0x12: return es1371->base_addr >> 16; case 0x13: return es1371->base_addr >> 24; - case 0x2c: return 0x74; /*Subsystem vendor ID*/ + case 0x2c: return 0x74; /* Subsystem vendor ID */ case 0x2d: return 0x12; case 0x2e: return 0x71; case 0x2f: return 0x13; - + case 0x34: return 0xdc; /*Capabilites pointer*/ - + case 0x3c: return es1371->int_line; case 0x3d: return 0x01; /*INTA*/ - + case 0x3e: return 0xc; /*Minimum grant*/ case 0x3f: return 0x80; /*Maximum latency*/ @@ -1168,18 +1175,18 @@ static void es1371_poll(void *p) if (es1371->int_ctrl & INT_UART_EN) { audiopci_log("UART INT Enabled\n"); - if (es1371->uart_ctrl & 0x80) { /*We currently don't implement MIDI Input.*/ + if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { /*We currently don't implement MIDI Input.*/ /*But if anything sets MIDI Input and Output together we'd have to take account of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is enabled as well but not in the MIDI Output portion*/ if (es1371->uart_ctrl & UART_CTRL_TXINTEN) es1371->int_status |= INT_STATUS_UART; else es1371->int_status &= ~INT_STATUS_UART; - } else if (!(es1371->uart_ctrl & 0x80) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ + } else if (!(es1371->uart_ctrl & UART_CTRL_RXINTEN) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ es1371->int_status |= INT_STATUS_UART; } - if (es1371->uart_ctrl & 0x80) { + if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { if (es1371->uart_ctrl & UART_CTRL_TXINTEN) es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); else @@ -1295,7 +1302,7 @@ static void generate_es1371_filter() low_fir_es1371_coef[n] /= gain; } -static void *es1371_init() +static void *es1371_init(const device_t *info) { es1371_t *es1371 = malloc(sizeof(es1371_t)); memset(es1371, 0, sizeof(es1371_t)); diff --git a/src/sound/snd_audiopci.h b/src/sound/snd_audiopci.h deleted file mode 100644 index 66600ed24..000000000 --- a/src/sound/snd_audiopci.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t es1371_device; diff --git a/src/sound/snd_cms.c b/src/sound/snd_cms.c index 5d3e73c8d..829399932 100644 --- a/src/sound/snd_cms.c +++ b/src/sound/snd_cms.c @@ -5,11 +5,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "device.h" #include "sound.h" -#include "snd_cms.h" #define MASTER_CLOCK 7159090 diff --git a/src/sound/snd_cms.h b/src/sound/snd_cms.h deleted file mode 100644 index 41b6d6059..000000000 --- a/src/sound/snd_cms.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t cms_device; diff --git a/src/sound/snd_emu8k.c b/src/sound/snd_emu8k.c index f5d19daac..946d8b7f6 100644 --- a/src/sound/snd_emu8k.c +++ b/src/sound/snd_emu8k.c @@ -7,12 +7,12 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "timer.h" #include "sound.h" #include "snd_emu8k.h" @@ -2143,7 +2143,8 @@ void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram) fatal("AWE32.RAW not found\n"); emu8k->rom = malloc(1024 * 1024); - fread(emu8k->rom, 1024 * 1024, 1, f); + if (fread(emu8k->rom, 1, 1048576, f) != 1048576) + fatal("emu8k_init(): Error reading data\n"); fclose(f); /*AWE-DUMP creates ROM images offset by 2 bytes, so if we detect this then correct it*/ diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 1f8fcfd3b..bcba6dc6f 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -5,16 +5,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../nmi.h" -#include "../pic.h" -#include "../dma.h" -#include "../timer.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "nmi.h" +#include "pic.h" +#include "dma.h" +#include "timer.h" +#include "device.h" #include "sound.h" #include "midi.h" -#include "snd_gus.h" enum { @@ -111,8 +110,8 @@ typedef struct gus_t uint8_t usrr; } gus_t; -static int gus_gf1_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; -static int gus_midi_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; +static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; +static int gus_midi_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1}; int gusfreqs[]= @@ -135,7 +134,7 @@ void pollgusirqs(gus_t *gus) gus->irqstatus2=0x60|c; if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80; gus->irqstatus|=0x20; - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); return; } @@ -143,16 +142,13 @@ void pollgusirqs(gus_t *gus) { gus->irqstatus2=0xA0|c; gus->irqstatus|=0x40; - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); return; } } gus->irqstatus2=0xE0; - if (!gus->irqstatus) { - if (gus->irq != 0) - picintc(1 << gus->irq); - } + if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq); } void gus_midi_update_int_status(gus_t *gus) @@ -174,7 +170,7 @@ void gus_midi_update_int_status(gus_t *gus) else gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; - if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != 0)) + if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1)) { picint(1 << gus->irq_midi); } @@ -221,6 +217,9 @@ void writegus(uint16_t addr, uint8_t val, void *p) } else gus->midi_status |= MIDI_INT_TRANSMIT; break; + case 0x302: /*Voice select*/ + gus->voice=val&31; + break; case 0x303: /*Global select*/ gus->global=val; break; @@ -463,9 +462,9 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); } break; case 0x307: /*DRAM access*/ - gus->addr&=0xFFFFF; if (gus->addr < gus->gus_end_ram) - gus->ram[gus->addr]=val; + gus->ram[gus->addr]=val; + gus->addr&=0xFFFFF; break; case 0x208: case 0x388: gus->adcommand = val; @@ -480,7 +479,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); { if (gus->sb_nmi) nmi = 1; - else + else if (gus->irq != -1) picint(1 << gus->irq); } } @@ -515,68 +514,23 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); switch (gus->reg_ctrl & 0x07) { case 0: - if (gus->latch_enable & 0x40) { - // GUS SDK: IRQ Control Register - // Channel 1 GF1 IRQ selector (bits 2-0) - // 0=reserved, do not use - // 1=IRQ2 - // 2=IRQ5 - // 3=IRQ3 - // 4=IRQ7 - // 5=IRQ11 - // 6=IRQ12 - // 7=IRQ15 - // Channel 2 MIDI IRQ selector (bits 5-3) - // 0=no interrupt - // 1=IRQ2 - // 2=IRQ5 - // 3=IRQ3 - // 4=IRQ7 - // 5=IRQ11 - // 6=IRQ12 - // 7=IRQ15 - // Combine both IRQs using channel 1 (bit 6) - // Reserved (bit 7) - // - // "If both channels are sharing an IRQ, channel 2's IRQ must be set to 0 and turn on bit 6. A - // bus conflict will occur if both latches are programmed with the same IRQ #." - if ((val & 7) != 0) - gus->irq = gus_gf1_irqs[val & 7]; - - if (val & 0x40) // "Combine both IRQs" - gus->irq_midi = gus->irq; - else - gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; - - gus->sb_nmi = val & 0x80; - } else { - // GUS SDK: DMA Control Register - // Channel 1 (bits 2-0) - // 0=NO DMA - // 1=DMA1 - // 2=DMA3 - // 3=DMA5 - // 4=DMA6 - // 5=DMA7 - // 6=? - // 7=? - // Channel 2 (bits 5-3) - // 0=NO DMA - // 1=DMA1 - // 2=DMA3 - // 3=DMA5 - // 4=DMA6 - // 5=DMA7 - // 6=? - // 7=? - // Combine both DMA channels using channel 1 (bit 6) - // Reserved (bit 7) - // - // "If both channels are sharing an DMA, channel 2's DMA must be set to 0 and turn on bit 6. A - // bus conflict will occur if both latches are programmed with the same DMA #." - if (gus_dmas[val & 7] != -1) - gus->dma = gus_dmas[val & 7]; - } + if (gus->latch_enable & 0x40) { + gus->irq = gus_gf1_irqs[val & 7]; + + if (val & 0x40) + { + if (gus->irq == -1) + gus->irq = gus->irq_midi = gus_gf1_irqs[(val >> 3) & 7]; + else + gus->irq_midi = gus->irq; + } + else + gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; + + gus->sb_nmi = val & 0x80; + } else { + gus->dma = gus_dmas[val & 7]; + } break; case 1: gus->gp1 = val; @@ -599,12 +553,13 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); break; case 0x206: - if (gus->sb_ctrl & 0x20) { - gus->ad_status |= 0x08; + gus->ad_status |= 0x08; + if (gus->sb_ctrl & 0x20) + { if (gus->sb_nmi) - nmi = 1; - else if (gus->irq != 0) - picint(1 << gus->irq); + nmi = 1; + else if (gus->irq != -1) + picint(1 << gus->irq); } break; case 0x20a: @@ -616,9 +571,10 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8); { if (gus->sb_nmi) nmi = 1; - else if (gus->irq != 0) + else if (gus->irq != -1) picint(1 << gus->irq); } + /*FALLTHROUGH*/ case 0x20d: gus->sb_2xc = val; break; @@ -666,27 +622,23 @@ uint8_t readgus(uint16_t addr, void *p) } break; - case 0x200: - val = 0xff; - break; + case 0x200: + return 0; case 0x206: /*IRQ status*/ val = gus->irqstatus & ~0x10; if (gus->ad_status & 0x19) val |= 0x10; - break; + return val; - case 0x20F: - val = 0; - break; + case 0x20F: + return 0; case 0x302: - val = gus->voice; - break; + return gus->voice; case 0x303: - val = gus->global; - break; + return gus->global; case 0x304: /*Global low*/ switch (gus->global) @@ -768,8 +720,7 @@ uint8_t readgus(uint16_t addr, void *p) } break; case 0x306: case 0x706: /*Revision level*/ - val = 0xff; - break; + return 0xff; /*Pre 3.7 - no mixer*/ case 0x307: /*DRAM access*/ val=gus->ram[gus->addr]; gus->addr&=0xFFFFF; @@ -777,7 +728,7 @@ uint8_t readgus(uint16_t addr, void *p) val = gus->ram[gus->addr]; else val = 0; - break; + return val; case 0x309: return 0; case 0x20b: @@ -820,6 +771,7 @@ uint8_t readgus(uint16_t addr, void *p) case 0x209: gus->ad_status &= ~0x01; nmi = 0; + /*FALLTHROUGH*/ case 0x389: val = gus->ad_data; break; @@ -846,7 +798,7 @@ void gus_poll_timer_1(void *p) gus->ad_status |= 0x40; if (gus->tctrl&4) { - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); gus->ad_status |= 0x04; gus->irqstatus |= 0x04; @@ -857,7 +809,7 @@ void gus_poll_timer_1(void *p) { gus->irqnext=0; gus->irqstatus|=0x80; - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); } @@ -878,7 +830,7 @@ void gus_poll_timer_2(void *p) gus->ad_status |= 0x20; if (gus->tctrl&8) { - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); gus->ad_status |= 0x02; gus->irqstatus |= 0x08; @@ -889,7 +841,7 @@ void gus_poll_timer_2(void *p) { gus->irqnext=0; gus->irqstatus|=0x80; - if (gus->irq != 0) + if (gus->irq != -1) picint(1 << gus->irq); } } @@ -1167,16 +1119,15 @@ void *gus_init(const device_t *info) io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); - timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); - timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); - timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); + timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); + timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); + timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); sound_add_handler(gus_get_buffer, gus); - input_msg = gus_input_msg; - input_sysex = gus_input_sysex; - midi_in_p = gus; - + if (device_get_config_int("receive_input")) + midi_in_handler(1, gus_input_msg, gus_input_sysex, gus); + return gus; } @@ -1254,7 +1205,10 @@ static const device_config_t gus_config[] = { NULL } } - }, + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } diff --git a/src/sound/snd_gus.h b/src/sound/snd_gus.h deleted file mode 100644 index 89e8ea331..000000000 --- a/src/sound/snd_gus.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t gus_device; diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index f368e3a21..1f1d57122 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -3,14 +3,13 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../lpt.h" -#include "../timer.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "lpt.h" +#include "timer.h" #include "sound.h" #include "filters.h" -#include "snd_lpt_dac.h" typedef struct lpt_dac_t { diff --git a/src/sound/snd_lpt_dac.h b/src/sound/snd_lpt_dac.h deleted file mode 100644 index d9f505353..000000000 --- a/src/sound/snd_lpt_dac.h +++ /dev/null @@ -1,2 +0,0 @@ -extern const lpt_device_t lpt_dac_device; -extern const lpt_device_t lpt_dac_stereo_device; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 72b5574af..973cb70de 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -3,14 +3,13 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../lpt.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "timer.h" +#include "lpt.h" #include "sound.h" #include "filters.h" -#include "snd_lpt_dss.h" typedef struct dss_t { diff --git a/src/sound/snd_lpt_dss.h b/src/sound/snd_lpt_dss.h deleted file mode 100644 index 07d37617a..000000000 --- a/src/sound/snd_lpt_dss.h +++ /dev/null @@ -1 +0,0 @@ -extern const lpt_device_t dss_device; diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 1ffc067f1..bdea9d911 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.18 2018/10/18 + * Version: @(#)snd_mpu401.c 1.0.20 2020/01/23 * * Authors: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2008-2018 DOSBox Team. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -27,20 +27,22 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../io.h" -#include "../machine/machine.h" -#include "../mca.h" -#include "../pic.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "86box_io.h" +#include "machine.h" +#include "mca.h" +#include "pic.h" +#include "timer.h" #include "sound.h" #include "snd_mpu401.h" #include "midi.h" -static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; -static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; + +static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; +static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; + enum { STATUS_OUTPUT_NOT_READY = 0x40, @@ -50,6 +52,7 @@ enum { int mpu401_standalone_enable = 0; + static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track); static void MPU401_EOIHandler(void *priv); @@ -83,12 +86,19 @@ MPU401_ReCalcClock(mpu_t *mpu) int32_t maxtempo = 240, mintempo = 16; int32_t freq; - if (mpu->clock.timebase >= 168) - maxtempo = 179; - if (mpu->clock.timebase == 144) + if (mpu->clock.timebase < 72) { + maxtempo = 240; + mintempo = 32; + } else if (mpu->clock.timebase < 120) { + maxtempo = 240; + mintempo = 16; + } else if (mpu->clock.timebase < 168) { maxtempo = 208; - if (mpu->clock.timebase >= 120) - maxtempo = 8; + mintempo = 8; + } else { + maxtempo = 179; + mintempo = 8; + } mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : @@ -138,14 +148,14 @@ MPU401_RunClock(mpu_t *mpu) static void -MPU401_QueueByte(mpu_t *mpu, uint8_t data) +MPU401_QueueByteEx(mpu_t *mpu, uint8_t data, int irq) { if (mpu->state.block_ack) { mpu->state.block_ack = 0; return; } - if (mpu->queue_used == 0) { + if ((mpu->queue_used == 0) && !mpu->irq_mask) { mpu->state.irq_pending = 1; picint(1 << mpu->irq); } @@ -164,6 +174,13 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data) } +static void +MPU401_QueueByte(mpu_t *mpu, uint8_t data) +{ + MPU401_QueueByteEx(mpu, data, 1); +} + + static void MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) { @@ -221,11 +238,16 @@ MPU401_Reset(mpu_t *mpu) { uint8_t i; +#ifdef DOSBOX_CODE if (mpu->mode == M_INTELLIGENT) { picintc(1 << mpu->irq); mpu->state.irq_pending = 0; } - +#else + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; +#endif + mpu->mode = M_INTELLIGENT; mpu->midi_thru = 0; mpu->state.rec = M_RECOFF; @@ -332,7 +354,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; /* In Intelligent mode, UART-only variants of the MPU-401 only support commands 0x3F and 0xFF. */ - if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) + if (!mpu->intelligent && (val != 0x3f) && (val != 0xff)) return; /* Hack: Enable midi through after the first mpu401 command is written. */ @@ -459,7 +481,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.midi_thru = 0; for (i = 0; i < 16; i++) { mpu->inputref[i].on = 0; - for (j = 0; i < 4; j++) + for (j = 0; j < 4; j++) mpu->inputref[i].key[j] = 0; } break; @@ -607,7 +629,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) was_uart = (mpu->mode == M_UART); MPU401_Reset(mpu); if (was_uart) - return; /* do not send ack in UART mode */ + return; break; /* default: @@ -624,6 +646,7 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) static int length, cnt; uint8_t i; +#ifdef DOSBOX_CODE if (mpu->mode == M_UART) { midi_raw_out_byte(val); return; @@ -633,6 +656,12 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val) mpu->state.command_byte = 0; return; } +#else + if (!mpu->intelligent || (mpu->mode == M_UART)) { + midi_raw_out_byte(val); + return; + } +#endif switch (mpu->state.command_byte) { /* 0xe# command data */ case 0x00: @@ -1055,7 +1084,7 @@ MPU401_ReadRaiseIRQ(mpu_t *mpu) picintc(1 << mpu->irq); mpu->state.irq_pending = 0; - if (mpu->queue_used) { + if (mpu->queue_used && !mpu->irq_mask) { /* Bytes remaining in queue, raise IRQ again. */ mpu->state.irq_pending = 1; picint(1 << mpu->irq); @@ -1079,10 +1108,17 @@ MPU401_ReadData(mpu_t *mpu) } /* Shouldn't this check mpu->mode? */ +#ifdef DOSBOX_CODE if (mpu->mode == M_UART) { MPU401_ReadRaiseIRQ(mpu); return ret; } +#else + if (!mpu->intelligent || (mpu->mode == M_UART)) { + MPU401_ReadRaiseIRQ(mpu); + return ret; + } +#endif if (mpu->state.rec_copy && !mpu->rec_queue_used) { mpu->state.rec_copy = 0; @@ -1186,10 +1222,17 @@ MPU401_Event(void *priv) mpu401_log("MPU-401 event callback\n"); +#ifdef DOSBOX_CODE if (mpu->mode == M_UART) { timer_disable(&mpu->mpu401_event_callback); return; } +#else + if (!mpu->intelligent || (mpu->mode == M_UART)) { + timer_disable(&mpu->mpu401_event_callback); + return; + } +#endif if (mpu->state.irq_pending) goto next_event; @@ -1283,8 +1326,8 @@ MPU401_NotesOff(mpu_t *mpu, int i) /*Input handler for SysEx */ -static int -MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) +int +MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) { mpu_t *mpu = (mpu_t *)p; int i; @@ -1328,8 +1371,8 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) /*Input handler for MIDI*/ -static void -MPU401_InputMsg(void *p, uint8_t *msg) +void +MPU401_InputMsg(void *p, uint8_t *msg) { mpu_t *mpu = (mpu_t *)p; int i, tick; @@ -1337,7 +1380,7 @@ MPU401_InputMsg(void *p, uint8_t *msg) uint8_t len = msg[3], key; uint8_t recdata[2], recmsg[4]; int send = 1, send_thru = 0; - int retrigger_thru = 0, midistatus = 0, chan, chrefnum; + int retrigger_thru = 0, chan, chrefnum; /* Abort if sysex transfer is in progress. */ if (!mpu->state.sysex_in_finished) { @@ -1347,10 +1390,13 @@ MPU401_InputMsg(void *p, uint8_t *msg) mpu401_log("MPU401 Input Msg\n"); +#ifdef DOSBOX_CODE if (mpu->mode == M_INTELLIGENT) { +#else + if (mpu->intelligent && (mpu->mode == M_INTELLIGENT)) { +#endif if (msg[0] < 0x80) { /* Expand running status */ - midistatus = 1; msg[2] = msg[1]; msg[1] = msg[0]; msg[0] = old_msg; @@ -1543,21 +1589,35 @@ MPU401_InputMsg(void *p, uint8_t *msg) } /* UART mode input. */ - for (i = 0; i < len; i++) { + for (i = 0; i < len; i++) MPU401_QueueByte(mpu, msg[i]); - picint(1 << mpu->irq); - } } void -mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) +mpu401_change_addr(mpu_t *mpu, uint16_t addr) +{ + if (mpu == NULL) + return; + if (mpu->addr) + io_removehandler(mpu->addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); + mpu->addr = addr; + if (mpu->addr) + io_sethandler(mpu->addr, 2, + mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); +} + + +void +mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input) { mpu->status = STATUS_INPUT_NOT_READY; mpu->irq = irq; mpu->queue_used = 0; mpu->queue_pos = 0; mpu->mode = M_UART; + mpu->addr = addr; /* Expalantion: MPU-401 starting in intelligent mode = Full MPU-401 intelligent mode capability; @@ -1566,16 +1626,19 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0; mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART"); - if (addr) - io_sethandler(addr, 2, + if (mpu->addr) + io_sethandler(mpu->addr, 2, mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); io_sethandler(0x2A20, 16, NULL, NULL, NULL, imf_write, NULL, NULL, mpu); - timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0); - timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0); - timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0); + timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0); + timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0); + timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0); MPU401_Reset(mpu); + + if (receive_input) + midi_in_handler(1, MPU401_InputMsg, MPU401_InputSysex, mpu); } @@ -1644,7 +1707,7 @@ mpu401_standalone_init(const device_t *info) mpu = malloc(sizeof(mpu_t)); memset(mpu, 0, sizeof(mpu_t)); - + mpu401_log("mpu_init\n"); if (info->flags & DEVICE_MCA) { @@ -1658,11 +1721,7 @@ mpu401_standalone_init(const device_t *info) irq = device_get_config_int("irq"); } - input_msg = MPU401_InputMsg; - input_sysex = MPU401_InputSysex; - midi_in_p = mpu; - - mpu401_init(mpu, base, irq, M_INTELLIGENT); + mpu401_init(mpu, base, irq, M_INTELLIGENT, device_get_config_int("receive_input")); return(mpu); } @@ -1719,6 +1778,26 @@ static const device_config_t mpu401_standalone_config[] = } } }, + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + "", "", -1 + } +}; + + +static const device_config_t mpu401_standalone_mca_config[] = +{ + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, { "", "", -1 } @@ -1742,5 +1821,5 @@ const device_t mpu401_mca_device = { NULL, NULL, NULL, - NULL + mpu401_standalone_mca_config }; diff --git a/src/sound/snd_mpu401.h b/src/sound/snd_mpu401.h index ce2ce54bf..99fe8b288 100644 --- a/src/sound/snd_mpu401.h +++ b/src/sound/snd_mpu401.h @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)sound_mpu401.h 1.0.4 2018/09/31 + * Version: @(#)sound_mpu401.h 1.0.5 2020/01/19 * * Author: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2008-2018 DOSBox Team. - * Copyright 2016-2018 Miran Grca. - * Copyright 2016-2018 TheCollector1995. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 TheCollector1995. */ #define MPU401_VERSION 0x15 @@ -70,9 +70,10 @@ typedef enum RecState typedef struct mpu_t { - int midi_thru; + uint16_t addr; int uart_mode, intelligent, - irq, + irq, irq_mask, + midi_thru, queue_pos, queue_used; uint8_t rx_data, is_mca, status, @@ -139,14 +140,19 @@ typedef struct mpu_t uint32_t key[4]; } chanref[5], inputref[16]; pc_timer_t mpu401_event_callback, mpu401_eoi_callback, - mpu401_reset_callback; + mpu401_reset_callback; } mpu_t; -extern int mpu401_standalone_enable; +extern int mpu401_standalone_enable, mpu401_already_loaded; + extern const device_t mpu401_device; extern const device_t mpu401_mca_device; extern uint8_t MPU401_ReadData(mpu_t *mpu); -extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode); +extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr); +extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input); extern void mpu401_device_add(void); + +extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort); +extern void MPU401_InputMsg(void *p, uint8_t *msg); diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 437ea62b5..6efc3fd5b 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -6,10 +6,10 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" #include "sound.h" #include "snd_opl.h" #include "snd_opl_backend.h" diff --git a/src/sound/snd_opl_backend.c b/src/sound/snd_opl_backend.c index 0a0e08d8e..2e8ae1df6 100644 --- a/src/sound/snd_opl_backend.c +++ b/src/sound/snd_opl_backend.c @@ -1,9 +1,17 @@ /* Copyright holders: Sarah Walker, SA1988 see COPYING for more details */ +#include +#include +#include +#include + +#include "86box.h" #include "nukedopl.h" #include "sound.h" #include "snd_opl_backend.h" +#include "cpu.h" +#include "mem.h" int opl_type = 0; @@ -129,6 +137,9 @@ opl_read(int nr, uint16_t addr) if (!(addr & 1)) return (opl[nr].status & opl[nr].status_mask) | (opl[nr].is_opl3 ? 0 : 0x06); + if (opl[nr].is_opl3 && ((addr & 3) == 3)) + return 0x00; + return opl[nr].is_opl3 ? 0 : 0xff; } diff --git a/src/sound/snd_pas16.c b/src/sound/snd_pas16.c index e10387df0..19aae50dc 100644 --- a/src/sound/snd_pas16.c +++ b/src/sound/snd_pas16.c @@ -5,21 +5,19 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../pic.h" -#include "../timer.h" -#include "../pit.h" -#include "../dma.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "pic.h" +#include "timer.h" +#include "pit.h" +#include "dma.h" +#include "device.h" #include "sound.h" #include "filters.h" #include "snd_mpu401.h" #include "snd_opl.h" -#include "snd_sb.h" #include "snd_sb_dsp.h" -#include "snd_pas16.h" /* Original PAS uses diff --git a/src/sound/snd_pas16.h b/src/sound/snd_pas16.h deleted file mode 100644 index d7a208faa..000000000 --- a/src/sound/snd_pas16.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t pas16_device; diff --git a/src/sound/snd_pssj.c b/src/sound/snd_pssj.c index 8714c540c..1f0000cb1 100644 --- a/src/sound/snd_pssj.c +++ b/src/sound/snd_pssj.c @@ -3,14 +3,13 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../timer.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "dma.h" +#include "pic.h" +#include "timer.h" +#include "device.h" #include "sound.h" -#include "snd_pssj.h" #include "snd_sn76489.h" diff --git a/src/sound/snd_pssj.h b/src/sound/snd_pssj.h deleted file mode 100644 index 71126f615..000000000 --- a/src/sound/snd_pssj.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t pssj_device; diff --git a/src/sound/snd_resid.cc b/src/sound/snd_resid.cc index a984323bd..931a4e1d0 100644 --- a/src/sound/snd_resid.cc +++ b/src/sound/snd_resid.cc @@ -3,7 +3,7 @@ #include #include #include "resid-fp/sid.h" -#include "../plat.h" +#include "plat.h" #include "snd_resid.h" diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index f86e85cd9..25ed6b87d 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -8,14 +8,14 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.16 2019/09/27 + * Version: @(#)sound_sb.c 1.0.17 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -24,20 +24,20 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mca.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "pic.h" #include "sound.h" #include "midi.h" #include "filters.h" #include "snd_emu8k.h" #include "snd_mpu401.h" #include "snd_opl.h" -#include "snd_sb.h" #include "snd_sb_dsp.h" //#define SB_DSP_RECORD_DEBUG @@ -679,9 +679,7 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; if (!(addr & 1)) - { mixer->index = val; - } else { // TODO: and this? 001h: @@ -721,6 +719,12 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) mixer->regs[0x46] = mixer->regs[0x47] = 8 << 4; mixer->regs[0x43] = 0; + + mixer->regs[0x83] = 0xff; + sb->dsp.sb_irqm8 = 0; + sb->dsp.sb_irqm16 = 0; + if (sb->mpu != NULL) + sb->mpu->irq_mask = 0; } else { @@ -728,6 +732,19 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) } switch (mixer->index) { + /* SB1/2 compatibility? */ + case 0x02: + mixer->regs[0x30] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + mixer->regs[0x31] = ((mixer->regs[0x02] & 0xf) << 4) | 0x8; + break; + case 0x06: + mixer->regs[0x34] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + mixer->regs[0x35] = ((mixer->regs[0x06] & 0xf) << 4) | 0x8; + break; + case 0x08: + mixer->regs[0x36] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + mixer->regs[0x37] = ((mixer->regs[0x08] & 0xf) << 4) | 0x8; + break; /* SBPro compatibility. Copy values to sb16 registers. */ case 0x22: mixer->regs[0x30] = (mixer->regs[0x22] & 0xF0) | 0x8; @@ -746,7 +763,8 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) mixer->regs[0x37] = ((mixer->regs[0x28] & 0xf) << 4) | 0x8; break; case 0x0A: - mixer->regs[0x3A] = (mixer->regs[0x0A]*3)+10; + // mixer->regs[0x3A] = (mixer->regs[0x0A]*3)+10; + mixer->regs[0x3A] = (mixer->regs[0x0A] << 5) | 0x18; break; case 0x2E: mixer->regs[0x38] = (mixer->regs[0x2E] & 0xF0) | 0x8; @@ -774,6 +792,34 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p) if (val & 0x40) sb_dsp_setdma16(&sb->dsp,6); if (val & 0x80) sb_dsp_setdma16(&sb->dsp,7); break; + + case 0x83: + /* Interrupt mask. */ + sb->dsp.sb_irqm8 = !(val & 0x01); + if (sb->dsp.sb_irqm8) + sb_irqc(&sb->dsp, 1); + sb->dsp.sb_irqm16 = !(val & 0x02); + if (sb->dsp.sb_irqm16) + sb_irqc(&sb->dsp, 0); + if (sb->mpu != NULL) { + sb->mpu->irq_mask = !(val & 0x04); + if (sb->mpu->irq_mask) { + picintc(1 << sb->mpu->irq); + sb->mpu->state.irq_pending = 0; + } + } + break; + + case 0x84: + /* MPU Control register, per the Linux source code. */ + if (sb->mpu != NULL) { + if ((val & 0x06) == 0x00) + mpu401_change_addr(sb->mpu, 0x330); + else if ((val & 0x06) == 0x04) + mpu401_change_addr(sb->mpu, 0x300); + else if ((val & 0x06) == 0x02) + mpu401_change_addr(sb->mpu, 0); + } } mixer->output_selector = mixer->regs[0x3C]; @@ -816,40 +862,56 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) { sb_t *sb = (sb_t *)p; sb_ct1745_mixer_t *mixer = &sb->mixer_sb16; - uint8_t temp; + uint8_t temp, ret = 0xff; if (!(addr & 1)) - return mixer->index; + ret = mixer->index; sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); if (mixer->index>=0x30 && mixer->index<=0x47) - { - return mixer->regs[mixer->index]; - } - switch (mixer->index) + ret = mixer->regs[mixer->index]; + else switch (mixer->index) { case 0x00: - return mixer->regs[mixer->index]; + ret = mixer->regs[mixer->index]; + break; /*SB Pro compatibility*/ case 0x04: - return ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); + ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0); + break; case 0x0a: - return (mixer->regs[0x3a] - 10) / 3; + // ret = (mixer->regs[0x3a] - 10) / 3; + ret = (mixer->regs[0x3a] >> 5); + break; + case 0x02: + ret = ((mixer->regs[0x30] >> 4) & 0x0f); + break; + case 0x06: + ret = ((mixer->regs[0x34] >> 4) & 0x0f); + break; + case 0x08: + ret = ((mixer->regs[0x36] >> 4) & 0x0f); + break; case 0x22: - return ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); + ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0); + break; case 0x26: - return ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); + ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0); + break; case 0x28: - return ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); + ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0); + break; case 0x2e: - return ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); + ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0); + break; case 0x48: // Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector). even when writing. // Also, the version I have (5.17) does not use the MIDI.L/R input selectors. it uses the volume to mute (Affecting the output, obviously) - return mixer->regs[mixer->index]; + ret = mixer->regs[mixer->index]; + break; case 0x80: /*TODO: Unaffected by mixer reset or soft reboot. @@ -858,37 +920,34 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) switch (sb->dsp.sb_irqnum) { - case 2: return 1; - case 5: return 2; - case 7: return 4; - case 10: return 8; + case 2: ret = 1; break; + case 5: ret = 2; break; + case 7: ret = 4; break; + case 10: ret = 8; break; } break; case 0x81: - { /* TODO: Unaffected by mixer reset or soft reboot. - * Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. - * Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, - including translated 16-bit DMA requests. - * Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA - requests to 8-bit ones, using the selected 8-bit DMA channel.*/ + * Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels. + * Disabling all 8-bit DMA channel bits disables 8-bit DMA requests, + including translated 16-bit DMA requests. + * Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA + requests to 8-bit ones, using the selected 8-bit DMA channel.*/ - uint8_t result=0; - switch (sb->dsp.sb_8_dmanum) - { - case 0: result |= 1; break; - case 1: result |= 2; break; - case 3: result |= 8; break; - } - switch (sb->dsp.sb_16_dmanum) - { - case 5: result |= 0x20; break; - case 6: result |= 0x40; break; - case 7: result |= 0x80; break; - } - return result; - } + ret = 0; + switch (sb->dsp.sb_8_dmanum) { + case 0: ret |= 1; break; + case 1: ret |= 2; break; + case 3: ret |= 8; break; + } + switch (sb->dsp.sb_16_dmanum) + { + case 5: ret |= 0x20; break; + case 6: ret |= 0x40; break; + case 7: ret |= 0x80; break; + } + break; /* The Interrupt status register, addressed as register 82h on the Mixer register map, is used by the ISR to determine whether the interrupt is meant for it or for some other ISR, @@ -900,23 +959,59 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p) temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000; if (sb->mpu) temp |= ((sb->mpu->state.irq_pending) ? 4 : 0); - return temp; + ret = temp; + break; + + case 0x83: + /* Interrupt mask. */ + ret = mixer->regs[mixer->index]; + break; + + case 0x84: + /* MPU Control. */ + if (sb->mpu == NULL) + ret = 0x02; + else { + if (sb->mpu->addr == 0x330) + ret = 0x00; + else if (sb->mpu->addr == 0x300) + ret = 0x04; + else if (sb->mpu->addr == 0) + ret = 0x02; + else + ret = 0x06; /* Should never happen. */ + } + break; + + case 0x90: + /* 3D Enhancement switch. */ + ret = mixer->regs[mixer->index]; + break; /* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */ - - + case 0xfd: + ret = 16; + break; + + case 0xfe: + ret = 6; + break; + default: sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } - return 0xff; + return ret; } void sb_ct1745_mixer_reset(sb_t* sb) { sb_ct1745_mixer_write(4,0,sb); sb_ct1745_mixer_write(5,0,sb); + + sb->mixer_sb16.regs[0xfd] = 16; + sb->mixer_sb16.regs[0xfe] = 6; } @@ -1018,7 +1113,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } -void *sb_1_init() +void *sb_1_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1042,14 +1137,13 @@ void *sb_1_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_15_init() +void *sb_15_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1073,15 +1167,14 @@ void *sb_15_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; - + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + return sb; } -void *sb_mcv_init() +void *sb_mcv_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip @@ -1102,13 +1195,12 @@ void *sb_mcv_init() sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; - + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + return sb; } -void *sb_2_init() +void *sb_2_init(const device_t *info) { /*sb2 port mappings. 220h or 240h. 2x0 to 2x3 -> CMS chip @@ -1153,14 +1245,13 @@ void *sb_2_init() else sound_add_handler(sb_get_buffer_sb2, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_v1_init() +void *sb_pro_v1_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) @@ -1190,14 +1281,13 @@ void *sb_pro_v1_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_v2_init() +void *sb_pro_v2_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip (18 voices) @@ -1226,14 +1316,13 @@ void *sb_pro_v2_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_mcv_init() +void *sb_pro_mcv_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (18 voices) @@ -1255,14 +1344,13 @@ void *sb_pro_mcv_init() sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_16_init() +void *sb_16_init(const device_t *info) { sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1288,15 +1376,13 @@ void *sb_16_init() if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); - sb_dsp_set_mpu(sb->mpu); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); } else sb->mpu = NULL; + sb_dsp_set_mpu(sb->mpu); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } @@ -1306,7 +1392,7 @@ int sb_awe32_available() return rom_present(L"roms/sound/awe32.raw"); } -void *sb_awe32_init() +void *sb_awe32_init(const device_t *info) { sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1336,15 +1422,14 @@ void *sb_awe32_init() if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(sb->mpu); } else sb->mpu = NULL; emu8k_init(&sb->emu8k, emu_addr, onboard_ram); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } @@ -1438,6 +1523,9 @@ static const device_config_t sb_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1479,6 +1567,9 @@ static const device_config_t sb_mcv_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1537,6 +1628,9 @@ static const device_config_t sb_pro_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1638,6 +1732,12 @@ static const device_config_t sb_16_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, { "", "", -1 } @@ -1782,6 +1882,12 @@ static const device_config_t sb_awe32_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, { "", "", -1 } diff --git a/src/sound/snd_sb.h b/src/sound/snd_sb.h deleted file mode 100644 index feaec6c78..000000000 --- a/src/sound/snd_sb.h +++ /dev/null @@ -1,47 +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. - * - * Sound Blaster emulation. - * - * Version: @(#)sound_sb.h 1.0.3 2018/03/18 - * - * Authors: Sarah Walker, - * Miran Grca, - * TheCollector1995, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#ifndef SOUND_SND_SB_H -# define SOUND_SND_SB_H - - -#define SADLIB 1 /* No DSP */ -#define SB1 2 /* DSP v1.05 */ -#define SB15 3 /* DSP v2.00 */ -#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */ -#define SBPRO 5 /* DSP v3.00 */ -#define SBPRO2 6 /* DSP v3.02 + OPL3 */ -#define SB16 7 /* DSP v4.05 + OPL3 */ -#define SADGOLD 8 /* AdLib Gold */ -#define SND_WSS 9 /* Windows Sound System */ -#define SND_PAS16 10 /* Pro Audio Spectrum 16 */ - - -extern const device_t sb_1_device; -extern const device_t sb_15_device; -extern const device_t sb_mcv_device; -extern const device_t sb_2_device; -extern const device_t sb_pro_v1_device; -extern const device_t sb_pro_v2_device; -extern const device_t sb_pro_mcv_device; -extern const device_t sb_16_device; -extern const device_t sb_awe32_device; - - -#endif /*SOUND_SND_SB_H*/ diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index dc40de587..5f86e79e6 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -12,17 +12,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../pic.h" -#include "../dma.h" -#include "../timer.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "pic.h" +#include "dma.h" +#include "timer.h" +#include "device.h" #include "filters.h" #include "sound.h" #include "midi.h" +#include "sound.h" #include "snd_mpu401.h" -#include "snd_sb.h" #include "snd_sb_dsp.h" @@ -182,9 +182,9 @@ void sb_irq(sb_dsp_t *dsp, int irq8) { sb_dsp_log("IRQ %i %02X\n", irq8, pic.mask); - if (irq8) + if (irq8 && !dsp->sb_irqm8) dsp->sb_irq8 = 1; - else + else if (!irq8 && !dsp->sb_irqm16) dsp->sb_irq16 = 1; picint(1 << dsp->sb_irqnum); @@ -841,7 +841,12 @@ sb_dsp_input_msg(void *p, uint8_t *msg) sb_dsp_t *dsp = (sb_dsp_t *) p; sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]); - + + if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) { + MPU401_InputMsg(mpu, msg); + return; + } + if (dsp->midi_in_sysex) { return; } @@ -867,6 +872,9 @@ sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) uint32_t i; + if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) + return MPU401_InputSysex(mpu, buffer, len, abort); + if (abort) { dsp->midi_in_sysex = 0; return 0; diff --git a/src/sound/snd_sb_dsp.h b/src/sound/snd_sb_dsp.h index 9e60dfaac..96743e77e 100644 --- a/src/sound/snd_sb_dsp.h +++ b/src/sound/snd_sb_dsp.h @@ -1,3 +1,15 @@ +#define SADLIB 1 /* No DSP */ +#define SB1 2 /* DSP v1.05 */ +#define SB15 3 /* DSP v2.00 */ +#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */ +#define SBPRO 5 /* DSP v3.00 */ +#define SBPRO2 6 /* DSP v3.02 + OPL3 */ +#define SB16 7 /* DSP v4.05 + OPL3 */ +#define SADGOLD 8 /* AdLib Gold */ +#define SND_WSS 9 /* Windows Sound System */ +#define SND_PAS16 10 /* Pro Audio Spectrum 16 */ + + typedef struct sb_dsp_t { int sb_type; @@ -49,6 +61,7 @@ typedef struct sb_dsp_t int sb_timei, sb_timeo; int sb_irq8, sb_irq16; + int sb_irqm8, sb_irqm16; uint8_t sb_asp_regs[256]; @@ -98,3 +111,4 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r); void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo); void sb_dsp_update(sb_dsp_t *dsp); +void sb_irqc(sb_dsp_t *dsp, int irq8); diff --git a/src/sound/snd_sn76489.c b/src/sound/snd_sn76489.c index 0f1b64ac1..1bcdcaf2d 100644 --- a/src/sound/snd_sn76489.c +++ b/src/sound/snd_sn76489.c @@ -4,9 +4,9 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "device.h" #include "sound.h" #include "snd_sn76489.h" diff --git a/src/sound/snd_speaker.c b/src/sound/snd_speaker.c index c6b9b1a8a..9423966db 100644 --- a/src/sound/snd_speaker.c +++ b/src/sound/snd_speaker.c @@ -20,9 +20,9 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" -#include "../pit.h" +#include "86box.h" +#include "timer.h" +#include "pit.h" #include "sound.h" #include "snd_speaker.h" diff --git a/src/sound/snd_ssi2001.c b/src/sound/snd_ssi2001.c index e20a08333..3f52e77a9 100644 --- a/src/sound/snd_ssi2001.c +++ b/src/sound/snd_ssi2001.c @@ -5,12 +5,11 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "device.h" #include "sound.h" #include "snd_resid.h" -#include "snd_ssi2001.h" typedef struct ssi2001_t diff --git a/src/sound/snd_ssi2001.h b/src/sound/snd_ssi2001.h deleted file mode 100644 index 83af6838a..000000000 --- a/src/sound/snd_ssi2001.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t ssi2001_device; diff --git a/src/sound/snd_wss.c b/src/sound/snd_wss.c index 838547997..5de5674b9 100644 --- a/src/sound/snd_wss.c +++ b/src/sound/snd_wss.c @@ -22,17 +22,16 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mca.h" -#include "../pic.h" -#include "../dma.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mca.h" +#include "pic.h" +#include "dma.h" +#include "device.h" #include "sound.h" #include "snd_ad1848.h" #include "snd_opl.h" -#include "snd_wss.h" /*530, 11, 3 - 530=23*/ @@ -99,18 +98,22 @@ static void wss_get_buffer(int32_t *buffer, int len, void *p) void *wss_init(const device_t *info) { wss_t *wss = malloc(sizeof(wss_t)); - memset(wss, 0, sizeof(wss_t)); - + + uint16_t addr = device_get_config_hex16("base"); + wss->opl_enabled = device_get_config_int("opl"); + opl3_init(&wss->opl); ad1848_init(&wss->ad1848); ad1848_setirq(&wss->ad1848, 7); ad1848_setdma(&wss->ad1848, 3); - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); - io_sethandler(0x0530, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); - io_sethandler(0x0534, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); + if (wss->opl_enabled) + io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); + + io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); + io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848); sound_add_handler(wss_get_buffer, wss); @@ -198,15 +201,45 @@ void wss_speed_changed(void *p) ad1848_speed_changed(&wss->ad1848); } +static const device_config_t wss_config[] = +{ + { + "base", "Address", CONFIG_HEX16, "", 0x530, + { + { + "0x530", 0x530 + }, + { + "0x604", 0x604 + }, + { + "0xe80", 0xe80 + }, + { + "0xf40", 0xf40 + }, + { + "" + } + } + }, + { + "opl", "Enable OPL", CONFIG_BINARY, "", 1 + }, + { + "", "", -1 + } +}; + const device_t wss_device = { "Windows Sound System", - DEVICE_ISA, 0, + DEVICE_ISA | DEVICE_AT, 0, wss_init, wss_close, NULL, NULL, wss_speed_changed, NULL, - NULL + wss_config }; const device_t ncr_business_audio_device = diff --git a/src/sound/snd_ym7128.c b/src/sound/snd_ym7128.c index c255295c6..79db28b38 100644 --- a/src/sound/snd_ym7128.c +++ b/src/sound/snd_ym7128.c @@ -2,7 +2,7 @@ #include #include #include -#include "../86box.h" +#include "86box.h" #include "snd_ym7128.h" diff --git a/src/sound/sound.c b/src/sound/sound.c index d3de46351..df17cb865 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -8,13 +8,13 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.27 2019/02/06 + * Version: @(#)sound.c 1.0.28 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -23,28 +23,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../cdrom/cdrom.h" -#include "../disk/hdc_ide.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "cdrom.h" +#include "hdc_ide.h" +#include "plat.h" #include "sound.h" #include "midi.h" #include "snd_opl.h" -#include "snd_cms.h" -#include "snd_adlib.h" -#include "snd_adlibgold.h" -#include "snd_audiopci.h" -#include "snd_gus.h" #include "snd_mpu401.h" -#if defined(DEV_BRANCH) && defined(USE_PAS16) -# include "snd_pas16.h" -#endif -#include "snd_sb.h" #include "snd_sb_dsp.h" -#include "snd_ssi2001.h" -#include "snd_wss.h" #include "filters.h" @@ -441,7 +430,7 @@ sound_reset(void) sound_realloc_buffers(); midi_device_init(); - midi_in_device_init(); + midi_in_device_init(); inital(); timer_add(&sound_poll_timer, sound_poll, NULL, 1); @@ -455,13 +444,20 @@ sound_reset(void) void sound_card_reset(void) { + /* Reset the MPU-401 already loaded flag and the chain of input/output handlers. */ + midi_in_handlers_clear(); + sound_card_init(); + if (mpu401_standalone_enable) mpu401_device_add(); + if (GUS) device_add(&gus_device); + if (GAMEBLASTER) device_add(&cms_device); + if (SSI2001) device_add(&ssi2001_device); } diff --git a/src/sound/sound.h b/src/sound/sound.h index 5410a5602..34f5d0ca9 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -67,4 +67,46 @@ extern void givealbuffer(void *buf); extern void givealbuffer_cd(void *buf); +#ifdef EMU_DEVICE_H +/* AdLib and AdLib Gold */ +extern const device_t adlib_device; +extern const device_t adlib_mca_device; +extern const device_t adgold_device; + +/* Ensoniq AudioPCI */ +extern const device_t es1371_device; + +/* Creative Labs Game Blaster */ +extern const device_t cms_device; + +/* Gravis UltraSound and UltraSound Max */ +extern const device_t gus_device; + +#if defined(DEV_BRANCH) && defined(USE_PAS16) +/* Pro Audio Spectrum 16 */ +extern const device_t pas16_device; +#endif + +/* PSSJ - What is this device? */ +extern const device_t pssj_device; + +/* Creative Labs Sound Blaster */ +extern const device_t sb_1_device; +extern const device_t sb_15_device; +extern const device_t sb_mcv_device; +extern const device_t sb_2_device; +extern const device_t sb_pro_v1_device; +extern const device_t sb_pro_v2_device; +extern const device_t sb_pro_mcv_device; +extern const device_t sb_16_device; +extern const device_t sb_awe32_device; + +/* Innovation SSI-2001 */ +extern const device_t ssi2001_device; + +/* Windows Sound System */ +extern const device_t wss_device; +extern const device_t ncr_business_audio_device; +#endif + #endif /*EMU_SOUND_H*/ diff --git a/src/sst_flash.c b/src/sst_flash.c new file mode 100644 index 000000000..7cb3e3292 --- /dev/null +++ b/src/sst_flash.c @@ -0,0 +1,458 @@ +/* + * 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 an SST flash chip. + * + * Version: @(#)sst_flash.c 1.0.1 2020/02/03 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "machine.h" +#include "timer.h" +#include "nvr.h" +#include "plat.h" + + +typedef struct sst_t +{ + uint8_t id, is_39, page_bytes, sdp; + + int command_state, id_mode, + dirty; + + uint32_t size, mask, + page_mask, page_base; + + uint8_t page_buffer[128]; + uint8_t *array; + + mem_mapping_t mapping[8], mapping_h[8]; + + pc_timer_t page_write_timer; +} sst_t; + + +static wchar_t flash_path[1024]; + + +#define SST_CHIP_ERASE 0x10 /* Both 29 and 39, 6th cycle */ +#define SST_SDP_DISABLE 0x20 /* Only 29, Software data protect disable and write - treat as write */ +#define SST_SECTOR_ERASE 0x30 /* Only 39, 6th cycle */ +#define SST_SET_ID_MODE_ALT 0x60 /* Only 29, 6th cycle */ +#define SST_ERASE 0x80 /* Both 29 and 39 */ + /* With data 60h on 6th cycle, it's alt. ID */ +#define SST_SET_ID_MODE 0x90 /* Both 29 and 39 */ +#define SST_BYTE_PROGRAM 0xa0 /* Both 29 and 39 */ +#define SST_CLEAR_ID_MODE 0xf0 /* Both 29 and 39 */ + /* 1st cycle variant only on 39 */ + +#define SST_ID_MANUFACTURER 0xbf /* SST Manufacturer's ID */ +#define SST_ID_SST29EE010 0x07 +#define SST_ID_SST29LE_VE010 0x08 +#define SST_ID_SST29EE020 0x10 +#define SST_ID_SST29LE_VE020 0x12 +#define SST_ID_SST39SF512 0xb4 +#define SST_ID_SST39SF010 0xb5 +#define SST_ID_SST39SF020 0xb6 +#define SST_ID_SST39SF040 0xb7 + + +static void +sst_sector_erase(sst_t *dev, uint32_t addr) +{ + memset(&dev->array[addr & (dev->mask & ~0xfff)], 0xff, 4096); + dev->dirty = 1; +} + + +static void +sst_new_command(sst_t *dev, uint32_t addr, uint8_t val) +{ + if (dev->command_state == 5) switch (val) { + case SST_CHIP_ERASE: + memset(dev->array, 0xff, 0x20000); + dev->command_state = 0; + break; + + case SST_SDP_DISABLE: + if (!dev->is_39) + dev->sdp = 0; + dev->command_state = 0; + break; + + case SST_SECTOR_ERASE: + if (dev->is_39) + sst_sector_erase(dev, addr); + dev->command_state = 0; + break; + + case SST_SET_ID_MODE_ALT: + dev->id_mode = 1; + dev->command_state = 0; + break; + + default: + dev->command_state = 0; + break; + } else switch (val) { + case SST_ERASE: + dev->command_state = 3; + break; + + case SST_SET_ID_MODE: + dev->id_mode = 1; + dev->command_state = 0; + break; + + case SST_BYTE_PROGRAM: + if (!dev->is_39) { + memset(dev->page_buffer, 0xff, 128); + dev->page_bytes = 0; + timer_on_auto(&dev->page_write_timer, 210.0); + } + dev->command_state = 6; + break; + + case SST_CLEAR_ID_MODE: + dev->id_mode = 0; + dev->command_state = 0; + break; + + default: + dev->command_state = 0; + break; + } +} + + +static void +sst_page_write(void *priv) +{ + sst_t *dev = (sst_t *) priv; + + memcpy(&(dev->array[dev->page_base]), dev->page_buffer, 128); + dev->dirty = 1; + dev->page_bytes = 0; + dev->command_state = 0; +} + + +static uint8_t +sst_read_id(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + + if ((addr & 0xffff) == 0) + return SST_ID_MANUFACTURER; /* SST */ + else if ((addr & 0xffff) == 1) + return dev->id; + else + return 0xff; +} + + +static void +sst_buf_write(sst_t *dev, uint32_t addr, uint8_t val) +{ + dev->page_buffer[addr & 0x0000007f] = val; + timer_disable(&dev->page_write_timer); + dev->page_bytes++; + if (dev->page_bytes >= 128) + sst_page_write(dev); + else + timer_set_delay_u64(&dev->page_write_timer, 210 * TIMER_USEC); +} + + +static void +sst_write(uint32_t addr, uint8_t val, void *p) +{ + sst_t *dev = (sst_t *) p; + + switch (dev->command_state) { + case 0: + case 3: + /* 1st and 4th Bus Write Cycle */ + if ((val == 0xf0) && dev->is_39 && (dev->command_state == 0)) { + if (dev->id_mode) + dev->id_mode = 0; + dev->command_state = 0; + } else if (((addr & 0x7fff) == 0x5555) && (val == 0xaa)) + dev->command_state++; + else { + if (!dev->is_39 && !dev->sdp && (dev->command_state == 0)) { + /* 29 series, software data protection off, start loading the page. */ + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state = 7; + sst_buf_write(dev, addr, val); + } + dev->command_state = 0; + } + break; + case 1: + case 4: + /* 2nd and 5th Bus Write Cycle */ + if (((addr & 0x7fff) == 0x2aaa) && (val == 0x55)) + dev->command_state++; + else + dev->command_state = 0; + break; + case 2: + case 5: + /* 3rd and 6th Bus Write Cycle */ + if ((addr & 0x7fff) == 0x5555) + sst_new_command(dev, addr, val); + else + dev->command_state = 0; + break; + case 6: + /* Page Load Cycle (29) / Data Write Cycle (39SF) */ + if (dev->is_39) { + dev->array[addr & dev->mask] = val; + dev->command_state = 0; + dev->dirty = 1; + } else { + dev->page_base = addr & dev->page_mask; /* First byte, A7 onwards of its address are the page mask. */ + dev->command_state++; + sst_buf_write(dev, addr, val); + } + break; + case 7: + if (!dev->is_39 && ((addr & dev->page_mask) == dev->page_base)) + sst_buf_write(dev, addr, val); + break; + } +} + + +static uint8_t +sst_read(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint8_t ret = 0xff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read_id(addr, p); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint16_t +sst_readw(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint16_t ret = 0xffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_read(addr, p) | (sst_read(addr + 1, p) << 8); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint16_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static uint32_t +sst_readl(uint32_t addr, void *p) +{ + sst_t *dev = (sst_t *) p; + uint32_t ret = 0xffffffff; + + addr &= 0x000fffff; + + if (dev->id_mode) + ret = sst_readw(addr, p) | (sst_readw(addr + 2, p) << 16); + else { + if ((addr >= biosaddr) && (addr <= (biosaddr + biosmask))) + ret = *(uint32_t *)&dev->array[addr - biosaddr]; + } + + return ret; +} + + +static void +sst_add_mappings(sst_t *dev) +{ + int i = 0, count; + uint32_t base, fbase; + uint32_t root_base; + + count = dev->size >> 16; + root_base = 0x100000 - dev->size; + + for (i = 0; i < count; i++) { + base = root_base + (i << 16); + fbase = base & biosmask; + + memcpy(&dev->array[fbase], &rom[base & biosmask], 0x10000); + + if (base >= 0xe0000) { + mem_mapping_add(&(dev->mapping[i]), base, 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + } + mem_mapping_add(&(dev->mapping_h[i]), (base | 0xfff00000), 0x10000, + sst_read, sst_readw, sst_readl, + sst_write, NULL, NULL, + dev->array + fbase, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROMCS, (void *) dev); + } +} + + +static void * +sst_init(const device_t *info) +{ + FILE *f; + sst_t *dev = malloc(sizeof(sst_t)); + memset(dev, 0, sizeof(sst_t)); + + size_t l = strlen(machine_get_internal_name_ex(machine))+1; + wchar_t *machine_name = (wchar_t *) malloc(l * sizeof(wchar_t)); + mbstowcs(machine_name, machine_get_internal_name_ex(machine), l); + l = wcslen(machine_name)+5; + wchar_t *flash_name = (wchar_t *)malloc(l*sizeof(wchar_t)); + swprintf(flash_name, l, L"%ls.bin", machine_name); + + if (wcslen(flash_name) <= 1024) + wcscpy(flash_path, flash_name); + else + wcsncpy(flash_path, flash_name, 1024); + + mem_mapping_disable(&bios_mapping); + mem_mapping_disable(&bios_high_mapping); + + dev->array = (uint8_t *) malloc(biosmask + 1); + memset(dev->array, 0xff, biosmask + 1); + + dev->id = info->local; + dev->is_39 = (dev->id >= SST_ID_SST39SF512); + + if (dev->id == SST_ID_SST39SF512) + dev->size = 0x10000; + else if ((dev->id == SST_ID_SST29EE020) || (dev->id == SST_ID_SST29LE_VE020) || (dev->id == SST_ID_SST39SF020)) + dev->size = 0x40000; + else if (dev->id == SST_ID_SST39SF040) + dev->size = 0x80000; + else + dev->size = 0x20000; + dev->mask = dev->size - 1; + dev->page_mask = dev->mask & 0xffffff80; /* Filter out A0-A6. */ + dev->sdp = 1; + + sst_add_mappings(dev); + + f = nvr_fopen(flash_path, L"rb"); + if (f) { + if (fread(&(dev->array[0x00000]), 1, dev->size, f) != dev->size) + fatal("Less than %i bytes read from the SST Flash ROM file\n", dev->size); + fclose(f); + } else + dev->dirty = 1; /* It is by definition dirty on creation. */ + + free(flash_name); + free(machine_name); + + if (!dev->is_39) + timer_add(&dev->page_write_timer, sst_page_write, dev, 0); + + return dev; +} + + +static void +sst_close(void *p) +{ + FILE *f; + sst_t *dev = (sst_t *)p; + + if (dev->dirty) { + f = nvr_fopen(flash_path, L"wb"); + fwrite(&(dev->array[0x00000]), dev->size, 1, f); + fclose(f); + } + + free(dev->array); + dev->array = NULL; + + free(dev); +} + + +const device_t sst_flash_29ee010_device = +{ + "SST 29EE010 Flash BIOS", + 0, + SST_ID_SST29EE010, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_29ee020_device = +{ + "SST 29EE020 Flash BIOS", + 0, + SST_ID_SST29EE020, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_39sf010_device = +{ + "SST 39SF010 Flash BIOS", + 0, + SST_ID_SST39SF010, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; + + +const device_t sst_flash_39sf020_device = +{ + "SST 39SF020 Flash BIOS", + 0, + SST_ID_SST39SF020, + sst_init, + sst_close, + NULL, + NULL, NULL, NULL, NULL +}; diff --git a/src/sst_flash.h b/src/sst_flash.h new file mode 100644 index 000000000..32607661c --- /dev/null +++ b/src/sst_flash.h @@ -0,0 +1,20 @@ +/* + * 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 an SST flash chip. + * + * Version: @(#)sst_flash.h 1.0.4 2020/02/03 + * + * Author: Melissa Goad, + * Copyright 2020 Melissa Goad. + */ + +extern const device_t sst_flash_29ee010_device; +extern const device_t sst_flash_29ee020_device; +extern const device_t sst_flash_39sf010_device; +extern const device_t sst_flash_39sf020_device; diff --git a/src/timer.h b/src/timer.h index 9941c3fdd..f75dc1727 100644 --- a/src/timer.h +++ b/src/timer.h @@ -1,7 +1,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ -#include "cpu/cpu.h" +#include "cpu.h" /* Maximum period, currently 1 second. */ #define MAX_USEC64 1000000ULL diff --git a/src/usb.c b/src/usb.c index 0577b5407..f962af311 100644 --- a/src/usb.c +++ b/src/usb.c @@ -5,7 +5,7 @@ #include #include #include -#include "io.h" +#include "86box_io.h" #include "mem.h" #include "usb.h" diff --git a/src/via_vt82c586b.c b/src/via_vt82c586b.c new file mode 100644 index 000000000..3e2887ecc --- /dev/null +++ b/src/via_vt82c586b.c @@ -0,0 +1,637 @@ +/* + * 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. + * + * Emulation of the VIA Apollo MVP3 southbridge + * + * Version: @(#)via_vt82c586b.c 1.0.2 2020/01/26 + * + * Authors: Sarah Walker, + * Miran Grca, + * Melissa Goad, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. + */ + +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include "86box.h" +#include "cdrom.h" +#include "cpu.h" +#include "scsi_device.h" +#include "scsi_cdrom.h" +#include "dma.h" +#include "86box_io.h" +#include "device.h" +#include "apm.h" +#include "keyboard.h" +#include "mem.h" +#include "timer.h" +#include "nvr.h" +#include "pci.h" +#include "pic.h" +#include "port_92.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "hdc_ide_sff8038i.h" +#include "zip.h" +#include "machine.h" +#include "via_vt82c586b.h" + + +#define ACPI_TIMER_FREQ 3579545 + +#define ACPI_IO_ENABLE (1 << 7) +#define ACPI_TIMER_32BIT (1 << 3) + + +typedef struct +{ + uint8_t pci_isa_regs[256]; + uint8_t ide_regs[256]; + uint8_t usb_regs[256]; + uint8_t power_regs[256]; + sff8038i_t * bm[2]; + nvr_t * nvr; + int nvr_enabled, slot; + + struct + { + uint16_t io_base; + } usb; + + struct + { + uint16_t io_base; + } power; +} via_vt82c586b_t; + + +static void +via_vt82c586b_reset_hard(void *priv) +{ + int i; + + via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *) priv; + uint16_t old_base = (via_vt82c586b->ide_regs[0x20] & 0xf0) | (via_vt82c586b->ide_regs[0x21] << 8); + + sff_bus_master_reset(via_vt82c586b->bm[0], old_base); + sff_bus_master_reset(via_vt82c586b->bm[1], old_base + 8); + + memset(via_vt82c586b->pci_isa_regs, 0, 256); + memset(via_vt82c586b->ide_regs, 0, 256); + memset(via_vt82c586b->usb_regs, 0, 256); + memset(via_vt82c586b->power_regs, 0, 256); + + via_vt82c586b->pci_isa_regs[0x00] = 0x06; via_vt82c586b->pci_isa_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->pci_isa_regs[0x02] = 0x86; via_vt82c586b->pci_isa_regs[0x03] = 0x05; /*VT82C586B*/ + via_vt82c586b->pci_isa_regs[0x04] = 0x0f; + via_vt82c586b->pci_isa_regs[0x07] = 0x02; + via_vt82c586b->pci_isa_regs[0x0a] = 0x01; + via_vt82c586b->pci_isa_regs[0x0b] = 0x06; + via_vt82c586b->pci_isa_regs[0x0e] = 0x80; + + via_vt82c586b->pci_isa_regs[0x48] = 0x01; + via_vt82c586b->pci_isa_regs[0x4a] = 0x04; + via_vt82c586b->pci_isa_regs[0x4f] = 0x03; + + via_vt82c586b->pci_isa_regs[0x50] = 0x24; + via_vt82c586b->pci_isa_regs[0x59] = 0x04; + + dma_e = 0x00; + for (i = 0; i < 8; i++) { + dma[i].ab &= 0xffff000f; + dma[i].ac &= 0xffff000f; + } + + pic_set_shadow(0); + + /* IDE registers */ + via_vt82c586b->ide_regs[0x00] = 0x06; via_vt82c586b->ide_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->ide_regs[0x02] = 0x71; via_vt82c586b->ide_regs[0x03] = 0x05; /*VT82C586B*/ + via_vt82c586b->ide_regs[0x04] = 0x80; + via_vt82c586b->ide_regs[0x06] = 0x80; via_vt82c586b->ide_regs[0x07] = 0x02; + via_vt82c586b->ide_regs[0x09] = 0x85; + via_vt82c586b->ide_regs[0x0a] = 0x01; + via_vt82c586b->ide_regs[0x0b] = 0x01; + + via_vt82c586b->ide_regs[0x10] = 0xf1; via_vt82c586b->ide_regs[0x11] = 0x01; + via_vt82c586b->ide_regs[0x14] = 0xf5; via_vt82c586b->ide_regs[0x15] = 0x03; + via_vt82c586b->ide_regs[0x18] = 0x71; via_vt82c586b->ide_regs[0x19] = 0x01; + via_vt82c586b->ide_regs[0x1c] = 0x75; via_vt82c586b->ide_regs[0x1d] = 0x03; + via_vt82c586b->ide_regs[0x20] = 0x01; via_vt82c586b->ide_regs[0x21] = 0xcc; + via_vt82c586b->ide_regs[0x3c] = 0x0e; + + via_vt82c586b->ide_regs[0x40] = 0x08; + via_vt82c586b->ide_regs[0x41] = 0x02; + via_vt82c586b->ide_regs[0x42] = 0x09; + via_vt82c586b->ide_regs[0x43] = 0x3a; + via_vt82c586b->ide_regs[0x44] = 0x68; + via_vt82c586b->ide_regs[0x46] = 0xc0; + via_vt82c586b->ide_regs[0x48] = 0xa8; via_vt82c586b->ide_regs[0x49] = 0xa8; + via_vt82c586b->ide_regs[0x4a] = 0xa8; via_vt82c586b->ide_regs[0x4b] = 0xa8; + via_vt82c586b->ide_regs[0x4c] = 0xff; + via_vt82c586b->ide_regs[0x4e] = 0xff; + via_vt82c586b->ide_regs[0x4f] = 0xff; + via_vt82c586b->ide_regs[0x50] = 0x03; via_vt82c586b->ide_regs[0x51] = 0x03; + via_vt82c586b->ide_regs[0x52] = 0x03; via_vt82c586b->ide_regs[0x53] = 0x03; + + via_vt82c586b->ide_regs[0x61] = 0x02; + via_vt82c586b->ide_regs[0x69] = 0x02; + + via_vt82c586b->usb_regs[0x00] = 0x06; via_vt82c586b->usb_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->usb_regs[0x02] = 0x38; via_vt82c586b->usb_regs[0x03] = 0x30; + via_vt82c586b->usb_regs[0x04] = 0x00; via_vt82c586b->usb_regs[0x05] = 0x00; + via_vt82c586b->usb_regs[0x06] = 0x00; via_vt82c586b->usb_regs[0x07] = 0x02; + via_vt82c586b->usb_regs[0x0a] = 0x03; + via_vt82c586b->usb_regs[0x0b] = 0x0c; + via_vt82c586b->usb_regs[0x0d] = 0x16; + via_vt82c586b->usb_regs[0x20] = 0x01; + via_vt82c586b->usb_regs[0x21] = 0x03; + via_vt82c586b->usb_regs[0x3d] = 0x04; + + via_vt82c586b->usb_regs[0x60] = 0x10; + via_vt82c586b->usb_regs[0xc1] = 0x20; + + via_vt82c586b->power_regs[0x00] = 0x06; via_vt82c586b->power_regs[0x01] = 0x11; /*VIA*/ + via_vt82c586b->power_regs[0x02] = 0x40; via_vt82c586b->power_regs[0x03] = 0x30; + via_vt82c586b->power_regs[0x04] = 0x00; via_vt82c586b->power_regs[0x05] = 0x00; + via_vt82c586b->power_regs[0x06] = 0x80; via_vt82c586b->power_regs[0x07] = 0x02; + via_vt82c586b->power_regs[0x08] = 0x10; /*Production version (3041)*/ + via_vt82c586b->power_regs[0x48] = 0x01; + + pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); + + pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED); + + ide_pri_disable(); + ide_sec_disable(); +} + + +static void +via_vt82c586b_ide_handlers(via_vt82c586b_t *dev) +{ + uint16_t main, side; + + ide_pri_disable(); + ide_sec_disable(); + + if (dev->ide_regs[0x09] & 0x01) { + main = (dev->ide_regs[0x11] << 8) | (dev->ide_regs[0x10] & 0xf8); + side = ((dev->ide_regs[0x15] << 8) | (dev->ide_regs[0x14] & 0xfc)) + 2; + } else { + main = 0x1f0; + side = 0x3f6; + } + ide_set_base(0, main); + ide_set_side(0, side); + + if (dev->ide_regs[0x09] & 0x04) { + main = (dev->ide_regs[0x19] << 8) | (dev->ide_regs[0x18] & 0xf8); + side = ((dev->ide_regs[0x1d] << 8) | (dev->ide_regs[0x1c] & 0xfc)) + 2; + } else { + main = 0x170; + side = 0x376; + } + ide_set_base(1, main); + ide_set_side(1, side); + + if (dev->ide_regs[0x04] & PCI_COMMAND_IO) { + if (dev->ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (dev->ide_regs[0x40] & 0x01) + ide_sec_enable(); + } +} + + +static void +via_vt82c586b_bus_master_handlers(via_vt82c586b_t *dev) +{ + uint16_t base = (dev->ide_regs[0x20] & 0xf0) | (dev->ide_regs[0x21] << 8); + + sff_bus_master_handler(dev->bm[0], (dev->ide_regs[0x04] & 1), base); + sff_bus_master_handler(dev->bm[1], (dev->ide_regs[0x04] & 1), base + 8); +} + + +static uint8_t +via_vt82c586b_read(int func, int addr, void *priv) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; + + uint8_t ret = 0xff; + int c; + + switch(func) { + case 0: + if ((addr >= 0x60) && (addr <= 0x6f)) { + c = (addr & 0x0e) >> 1; + if (addr & 0x01) + ret = (dma[c].ab & 0x0000ff00) >> 8; + else { + ret = (dma[c].ab & 0x000000f0); + ret |= (!!(dma_e & (1 << c)) << 3); + } + } else + ret = dev->pci_isa_regs[addr]; + break; + case 1: + ret = dev->ide_regs[addr]; + break; + case 2: + ret = dev->usb_regs[addr]; + break; + case 3: + ret = dev->power_regs[addr]; + break; + } + + return ret; +} + + +static uint8_t +usb_reg_read(uint16_t addr, void *p) +{ + uint8_t ret = 0xff; + + switch (addr & 0x1f) { + case 0x10: case 0x11: case 0x12: case 0x13: + /* Port status */ + ret = 0x00; + break; + } + + return ret; +} + + +static void +usb_reg_write(uint16_t addr, uint8_t val, void *p) +{ +} + + +static void +nvr_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->nvr_enabled) + nvr_at_handler(0, 0x0074, dev->nvr); + + if ((dev->pci_isa_regs[0x5b] & 0x02) && (dev->pci_isa_regs[0x48] & 0x08)) + nvr_at_handler(1, 0x0074, dev->nvr); +} + + +static void +usb_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->usb.io_base != 0x0000) + io_removehandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); + + dev->usb.io_base = (dev->usb_regs[0x20] & ~0x1f) | (dev->usb_regs[0x21] << 8); + + if ((dev->usb_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (dev->usb.io_base != 0x0000)) + io_sethandler(dev->usb.io_base, 0x20, usb_reg_read, NULL, NULL, usb_reg_write, NULL, NULL, dev); +} + + +static uint8_t +power_reg_read(uint16_t addr, void *p) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) p; + + uint32_t timer; + uint8_t ret = 0xff; + + switch (addr & 0xff) { + case 0x08: case 0x09: case 0x0a: case 0x0b: + /* ACPI timer */ + timer = (tsc * ACPI_TIMER_FREQ) / machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; + if (!(dev->power_regs[0x41] & ACPI_TIMER_32BIT)) + timer &= 0x00ffffff; + ret = (timer >> (8 * (addr & 3))) & 0xff; + break; + } + + return ret; +} + + +static void +power_reg_write(uint16_t addr, uint8_t val, void *p) +{ +} + + +static void +power_update_io_mapping(via_vt82c586b_t *dev) +{ + if (dev->power.io_base != 0x0000) + io_removehandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); + + dev->power.io_base = (dev->power_regs[0x49] << 8); + + if ((dev->power_regs[0x41] & ACPI_IO_ENABLE) && (dev->power.io_base != 0x0000)) + io_sethandler(dev->power.io_base, 0x100, power_reg_read, NULL, NULL, power_reg_write, NULL, NULL, dev); +} + + +static void +via_vt82c586b_write(int func, int addr, uint8_t val, void *priv) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) priv; + int c; + + if (func > 3) + return; + + switch(func) { + case 0: /* PCI-ISA bridge */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || ((addr >= 8) && (addr < 0x40)) || + (addr == 0x49) || (addr == 0x4b) || ((addr >= 0x51) && (addr < 0x54)) || ((addr >= 0x5d) && (addr < 0x60)) || + ((addr >= 0x68) && (addr < 0x6a)) || (addr >= 0x73)) + return; + + switch (addr) { + case 0x04: + dev->pci_isa_regs[0x04] = (val & 8) | 7; + break; + case 0x07: + dev->pci_isa_regs[0x07] &= ~(val & 0xb0); + break; + + case 0x47: + if ((val & 0x81) == 0x81) + resetx86(); + pic_set_shadow(!!(val & 0x10)); + pci_elcr_set_enabled(!!(val & 0x20)); + dev->pci_isa_regs[0x47] = val & 0xfe; + break; + case 0x48: + dev->pci_isa_regs[0x48] = val; + nvr_update_io_mapping(dev); + break; + + case 0x54: + pci_set_irq_level(PCI_INTA, !(val & 8)); + pci_set_irq_level(PCI_INTB, !(val & 4)); + pci_set_irq_level(PCI_INTC, !(val & 2)); + pci_set_irq_level(PCI_INTD, !(val & 1)); + break; + case 0x55: + pci_set_irq_routing(PCI_INTD, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ0, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x55] = val; + break; + case 0x56: + pci_set_irq_routing(PCI_INTA, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_irq_routing(PCI_INTB, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x56] = val; + break; + case 0x57: + pci_set_irq_routing(PCI_INTC, (val & 0xf0) ? (val >> 4) : PCI_IRQ_DISABLED); + pci_set_mirq_routing(PCI_MIRQ1, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x57] = val; + break; + case 0x58: + pci_set_mirq_routing(PCI_MIRQ2, (val & 0x0f) ? (val & 0x0f) : PCI_IRQ_DISABLED); + dev->pci_isa_regs[0x58] = val; + break; + case 0x5b: + dev->pci_isa_regs[0x5b] = val; + nvr_update_io_mapping(dev); + break; + + case 0x60: case 0x62: case 0x64: case 0x66: + case 0x6a: case 0x6c: case 0x6e: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffffff0f) | (val & 0xf0); + dma[c].ac = (dma[c].ac & 0xffffff0f) | (val & 0xf0); + if (val & 0x08) + dma_e |= (1 << c); + else + dma_e &= ~(1 << c); + break; + case 0x61: case 0x63: case 0x65: case 0x67: + case 0x6b: case 0x6d: case 0x6f: + c = (addr & 0x0e) >> 1; + dma[c].ab = (dma[c].ab & 0xffff00ff) | (val << 8); + dma[c].ac = (dma[c].ac & 0xffff00ff) | (val << 8); + break; + + case 0x70: case 0x71: case 0x72: case 0x73: + dev->pci_isa_regs[(addr - 0x44)] = val; + break; + } + break; + + case 1: /* IDE regs */ + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 8) || ((addr >= 0xa) && (addr < 0x0d)) || + ((addr >= 0x0e) && (addr < 0x10)) || ((addr >= 0x12) && (addr < 0x13)) || + ((addr >= 0x16) && (addr < 0x17)) || ((addr >= 0x1a) && (addr < 0x1b)) || + ((addr >= 0x1e) && (addr < 0x1f)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x54) && (addr < 0x60)) || + ((addr >= 0x52) && (addr < 0x68)) || (addr >= 0x62)) + return; + + switch (addr) { + case 0x04: + dev->ide_regs[0x04] = val & 0x85; + via_vt82c586b_ide_handlers(dev); + via_vt82c586b_bus_master_handlers(dev); + break; + case 0x07: + dev->ide_regs[0x07] &= ~(val & 0xf1); + break; + + case 0x09: + dev->ide_regs[0x09] = (val & 0x05) | 0x8a; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x10: + dev->ide_regs[0x10] = (val & 0xf8) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x11: + dev->ide_regs[0x11] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x14: + dev->ide_regs[0x14] = (val & 0xfc) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x15: + dev->ide_regs[0x15] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x18: + dev->ide_regs[0x18] = (val & 0xf8) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x19: + dev->ide_regs[0x19] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x1c: + dev->ide_regs[0x1c] = (val & 0xfc) | 1; + via_vt82c586b_ide_handlers(dev); + break; + case 0x1d: + dev->ide_regs[0x1d] = val; + via_vt82c586b_ide_handlers(dev); + break; + + case 0x20: + dev->ide_regs[0x20] = (val & 0xf0) | 1; + via_vt82c586b_bus_master_handlers(dev); + break; + case 0x21: + dev->ide_regs[0x21] = val; + via_vt82c586b_bus_master_handlers(dev); + break; + + case 0x3d: + sff_set_irq_mode(dev->bm[0], val); + sff_set_irq_mode(dev->bm[1], val); + break; + + case 0x40: + dev->ide_regs[0x40] = val; + via_vt82c586b_ide_handlers(dev); + break; + + default: + dev->ide_regs[addr] = val; + break; + } + break; + + case 2: + /* Read-only addresses */ + if ((addr < 4) || (addr == 5) || (addr == 6) || ((addr >= 8) && (addr < 0xd)) || + ((addr >= 0xe) && (addr < 0x20)) || ((addr >= 0x22) && (addr < 0x3c)) || + ((addr >= 0x3e) && (addr < 0x40)) || ((addr >= 0x42) && (addr < 0x44)) || + ((addr >= 0x46) && (addr < 0xc0)) || (addr >= 0xc2)) + return; + + switch (addr) { + case 0x04: + dev->usb_regs[0x04] = val & 0x97; + usb_update_io_mapping(dev); + break; + case 0x07: + dev->usb_regs[0x07] &= ~(val & 0x78); + break; + + case 0x20: + dev->usb_regs[0x20] = (val & ~0x1f) | 1; + usb_update_io_mapping(dev); + break; + case 0x21: + dev->usb_regs[0x21] = val; + usb_update_io_mapping(dev); + break; + + default: + dev->usb_regs[addr] = val; + break; + } + break; + + case 3: + /* Read-only addresses */ + if ((addr < 0xd) || ((addr >= 0xe) && (addr < 0x40)) || (addr == 0x43) || (addr == 0x48) || + ((addr >= 0x4a) && (addr < 0x50)) || (addr >= 0x54)) + return; + + switch (addr) { + case 0x41: case 0x49: + dev->power_regs[addr] = val; + power_update_io_mapping(dev); + break; + + default: + dev->power_regs[addr] = val; + break; + } + } +} + + +static void +*via_vt82c586b_init(const device_t *info) +{ + via_vt82c586b_t *dev = (via_vt82c586b_t *) malloc(sizeof(via_vt82c586b_t)); + memset(dev, 0, sizeof(via_vt82c586b_t)); + + dev->slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, via_vt82c586b_read, via_vt82c586b_write, dev); + + dev->bm[0] = device_add_inst(&sff8038i_device, 1); + sff_set_slot(dev->bm[0], dev->slot); + sff_set_irq_mode(dev->bm[0], 0); + sff_set_irq_pin(dev->bm[0], PCI_INTA); + + dev->bm[1] = device_add_inst(&sff8038i_device, 2); + sff_set_slot(dev->bm[1], dev->slot); + sff_set_irq_mode(dev->bm[1], 0); + sff_set_irq_pin(dev->bm[1], PCI_INTA); + + dev->nvr = device_add(&via_nvr_device); + + via_vt82c586b_reset_hard(dev); + + device_add(&port_92_pci_device); + + dma_alias_set(); + + pci_enable_mirq(0); + pci_enable_mirq(1); + pci_enable_mirq(2); + + return dev; +} + +static void +via_vt82c586b_close(void *p) +{ + via_vt82c586b_t *via_vt82c586b = (via_vt82c586b_t *)p; + + free(via_vt82c586b); +} + +const device_t via_vt82c586b_device = +{ + "VIA VT82C586B", + DEVICE_PCI, + 0, + via_vt82c586b_init, + via_vt82c586b_close, + NULL, + NULL, + NULL, + NULL, + NULL +}; diff --git a/src/video/vid_ht216.h b/src/via_vt82c586b.h similarity index 51% rename from src/video/vid_ht216.h rename to src/via_vt82c586b.h index abb15bba9..c2fd06a57 100644 --- a/src/video/vid_ht216.h +++ b/src/via_vt82c586b.h @@ -4,18 +4,17 @@ * PC systems and compatibles from 1981 through fairly recent * system designs based on the PCI bus. * - * This file is part of the 86Box distribution. + * Emulation of the VIA Apollo MVP3 southbridge * - * Video 7 VGA 1024i emulation header. - * - * Version: @(#)vid_ht216.h 1.0.1 2019/10/01 + * Version: @(#)via_vt82c586b.c 1.0.0 2020/01/14 * * Authors: Sarah Walker, * Miran Grca, + * Melissa Goad, * - * Copyright 2019 Sarah Walker. - * Copyright 2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2020 Melissa Goad. */ -extern const device_t g2_gc205_device; -extern const device_t v7_vga_1024i_device; -extern const device_t ht216_32_pb410a_device; + +extern const device_t via_vt82c586b_device; diff --git a/src/video/vid_ati18800.c b/src/video/vid_ati18800.c index 648772c77..2a4f9380d 100644 --- a/src/video/vid_ati18800.c +++ b/src/video/vid_ati18800.c @@ -8,27 +8,26 @@ * * ATI 18800 emulation (VGA Edge-16) * - * Version: @(#)vid_ati18800.c 1.0.14 2018/10/02 + * Version: @(#)vid_ati18800.c 1.0.17 2020/01/20 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" #include "video.h" -#include "vid_ati18800.h" #include "vid_ati_eeprom.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -71,7 +70,7 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p) ati18800_t *ati18800 = (ati18800_t *)p; svga_t *svga = &ati18800->svga; uint8_t old; - + if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1)) addr ^= 0x60; @@ -86,6 +85,7 @@ static void ati18800_out(uint16_t addr, uint8_t val, void *p) { case 0xb0: svga_recalctimings(svga); + break; case 0xb2: case 0xbe: if (ati18800->regs[0xbe] & 8) /*Read/write bank mode*/ @@ -129,7 +129,7 @@ static uint8_t ati18800_in(uint16_t addr, void *p) { ati18800_t *ati18800 = (ati18800_t *)p; svga_t *svga = &ati18800->svga; - uint8_t temp; + uint8_t temp = 0xff; if (((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && !(svga->miscout&1)) addr ^= 0x60; @@ -210,19 +210,27 @@ static void *ati18800_init(const device_t *info) rom_init(&ati18800->bios_rom, BIOS_ROM_PATH_EDGE16, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; }; - - svga_init(&ati18800->svga, ati18800, 1 << 20, /*512kb*/ - ati18800_recalctimings, - ati18800_in, ati18800_out, - NULL, - NULL); + + if (info->local == ATI18800_EDGE16) { + svga_init(&ati18800->svga, ati18800, 1 << 18, /*256kb*/ + ati18800_recalctimings, + ati18800_in, ati18800_out, + NULL, + NULL); + } else { + svga_init(&ati18800->svga, ati18800, 1 << 19, /*512kb*/ + ati18800_recalctimings, + ati18800_in, ati18800_out, + NULL, + NULL); + } io_sethandler(0x01ce, 0x0002, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); - io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); + io_sethandler(0x03c0, 0x0020, ati18800_in, NULL, NULL, ati18800_out, NULL, NULL, ati18800); ati18800->svga.miscout = 1; - ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0); + ati_eeprom_load(&ati18800->eeprom, L"ati18800.nvr", 0); return ati18800; } diff --git a/src/video/vid_ati18800.h b/src/video/vid_ati18800.h deleted file mode 100644 index b41facab3..000000000 --- a/src/video/vid_ati18800.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t ati18800_wonder_device; -extern const device_t ati18800_vga88_device; -extern const device_t ati18800_device; diff --git a/src/video/vid_ati28800.c b/src/video/vid_ati28800.c index a0c883c33..29dd9cc4f 100644 --- a/src/video/vid_ati28800.c +++ b/src/video/vid_ati28800.c @@ -25,18 +25,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" #include "video.h" -#include "vid_ati28800.h" #include "vid_ati_eeprom.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_sc1502x_ramdac.h" #define VGAWONDERXL 1 @@ -190,8 +188,7 @@ ati28800_out(uint16_t addr, uint8_t val, void *p) return; if ((ati28800->regs[0xb4] & 0x20) && ((svga->crtc[0x08] & 0x7f) && (svga->crtc[0x14] & 0x1f))) return; - if ((ati28800->regs[0xb4] & 0x40) && (((svga->crtcreg >= 0x00) && (svga->crtcreg <= 0x06)) && - (svga->crtc[0x07] & 0x10) != 0x10)) + if ((ati28800->regs[0xb4] & 0x40) && ((svga->crtcreg <= 0x06) && (svga->crtc[0x07] & 0x10) != 0x10)) return; old = svga->crtc[svga->crtcreg]; diff --git a/src/video/vid_ati28800.h b/src/video/vid_ati28800.h deleted file mode 100644 index 9db0fa7bc..000000000 --- a/src/video/vid_ati28800.h +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -extern const device_t ati28800_device; -extern const device_t ati28800k_device; -extern const device_t compaq_ati28800_device; -#if defined(DEV_BRANCH) && defined(USE_XL24) -extern const device_t ati28800_wonderxl24_device; -#endif diff --git a/src/video/vid_ati68860_ramdac.c b/src/video/vid_ati68860_ramdac.c index c814352b2..e0af06b45 100644 --- a/src/video/vid_ati68860_ramdac.c +++ b/src/video/vid_ati68860_ramdac.c @@ -41,19 +41,34 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_ati68860_ramdac.h" #include "vid_svga_render.h" -void -ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga) +typedef struct ati68860_ramdac_t { + uint8_t regs[16]; + void (*render)(struct svga_t *svga); + + int dac_addr, dac_pos; + int dac_r, dac_g; + PALETTE pal; + uint32_t pallook[2]; + + int ramdac_type; +} ati68860_ramdac_t; + + +void +ati68860_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) +{ + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + switch (addr) { case 0: svga_out(0x3c8, val, svga); @@ -143,8 +158,9 @@ ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_ } uint8_t -ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) +ati68860_ramdac_in(uint16_t addr, void *p, svga_t *svga) { + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; uint8_t temp = 0; switch (addr) { @@ -180,8 +196,9 @@ ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) void -ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type) +ati68860_set_ramdac_type(void *p, int type) { + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; int c; if (ramdac->ramdac_type != type) { @@ -211,6 +228,55 @@ ati68860_ramdac_init(const device_t *info) } +void +ati68860_ramdac_set_render(void *p, svga_t *svga) +{ + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + + svga->render = ramdac->render; +} + + +void +ati68860_ramdac_set_pallook(void *p, int i, uint32_t col) +{ + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) p; + + ramdac->pallook[i] = col; +} + + +void +ati68860_hwcursor_draw(svga_t *svga, int displine) +{ + ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; + int x, offset; + uint8_t dat; + uint32_t col0 = ramdac->pallook[0]; + uint32_t col1 = ramdac->pallook[1]; + + offset = svga->hwcursor_latch.xoff; + for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) { + dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; + dat >>= 2; + if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; + else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; + dat >>= 2; + offset += 4; + } + + svga->hwcursor_latch.addr += 16; +} + + static void ati68860_ramdac_close(void *priv) { diff --git a/src/video/vid_ati68860_ramdac.h b/src/video/vid_ati68860_ramdac.h deleted file mode 100644 index 33e59ebc3..000000000 --- a/src/video/vid_ati68860_ramdac.h +++ /dev/null @@ -1,36 +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. - * - * ATI 68860 RAMDAC emulation header (for Mach64) - * - * Version: @(#)vid_ati68860.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct ati68860_ramdac_t -{ - uint8_t regs[16]; - void (*render)(struct svga_t *svga); - - int dac_addr, dac_pos; - int dac_r, dac_g; - PALETTE pal; - uint32_t pallook[2]; - - int ramdac_type; -} ati68860_ramdac_t; - -extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga); -extern uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga); -extern void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type); - -extern const device_t ati68860_ramdac_device; diff --git a/src/video/vid_ati_eeprom.c b/src/video/vid_ati_eeprom.c index 3a01bfedd..ea499788d 100644 --- a/src/video/vid_ati_eeprom.c +++ b/src/video/vid_ati_eeprom.c @@ -8,23 +8,23 @@ * * Emulation of the EEPROM on select ATI cards. * - * Version: @(#)vid_ati_eeprom.c 1.0.2 2018/04/11 + * Version: @(#)vid_ati_eeprom.c 1.0.3 2020/01/20 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../timer.h" -#include "../nvr.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" +#include "nvr.h" #include "vid_ati_eeprom.h" @@ -58,15 +58,20 @@ enum void ati_eeprom_load(ati_eeprom_t *eeprom, wchar_t *fn, int type) { FILE *f; + int size; eeprom->type = type; - wcscpy(eeprom->fn, fn); + if (wcslen(fn) <= 256) + wcscpy(eeprom->fn, fn); + else + wcsncpy(eeprom->fn, fn, 256); f = nvr_fopen(eeprom->fn, L"rb"); - if (!f) - { - memset(eeprom->data, 0, eeprom->type ? 512 : 128); + size = eeprom->type ? 512 : 128; + if (!f) { + memset(eeprom->data, 0xff, size); return; } - fread(eeprom->data, 1, eeprom->type ? 512 : 128, f); + if (fread(eeprom->data, 1, size, f) != size) + memset(eeprom->data, 0, size); fclose(f); } diff --git a/src/video/vid_ati_mach64.c b/src/video/vid_ati_mach64.c index 03f7309f3..576b2c774 100644 --- a/src/video/vid_ati_mach64.c +++ b/src/video/vid_ati_mach64.c @@ -23,20 +23,18 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../pci.h" -#include "../rom.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "mem.h" +#include "timer.h" +#include "pci.h" +#include "rom.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_ati68860_ramdac.h" #include "vid_ati_eeprom.h" -#include "vid_ics2595.h" #ifdef CLAMP #undef CLAMP @@ -460,8 +458,6 @@ uint8_t mach64_in(uint16_t addr, void *p) void mach64_recalctimings(svga_t *svga) { mach64_t *mach64 = (mach64_t *)svga->p; - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; - ics2595_t *clock_gen = (ics2595_t *) svga->clock_gen; if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) { @@ -471,7 +467,7 @@ void mach64_recalctimings(svga_t *svga) svga->hdisp_time = svga->hdisp = ((mach64->crtc_h_total_disp >> 16) & 255) + 1; svga->vsyncstart = (mach64->crtc_v_sync_strt_wid & 2047) + 1; svga->rowoffset = (mach64->crtc_off_pitch >> 22); - svga->clock = (cpuclock * (double)(1ull << 32)) / clock_gen->output_clock; + svga->clock = (cpuclock * (double)(1ull << 32)) / ics2595_getclock(svga->clock_gen); svga->ma_latch = (mach64->crtc_off_pitch & 0x1fffff) * 2; svga->linedbl = svga->rowcount = 0; svga->split = 0xffffff; @@ -479,7 +475,7 @@ void mach64_recalctimings(svga_t *svga) svga->rowcount = mach64->crtc_gen_cntl & 1; svga->rowoffset <<= 1; if (mach64->type == MACH64_GX) - svga->render = ramdac->render; + ati68860_ramdac_set_render(svga->ramdac, svga); switch ((mach64->crtc_gen_cntl >> 8) & 7) { case 1: @@ -668,6 +664,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11e: case 0x11f: WRITE8(addr, mach64->dst_height_width, val); + /*FALLTHROUGH*/ case 0x113: if (((addr & 0x3ff) == 0x11b || (addr & 0x3ff) == 0x11f || (addr & 0x3ff) == 0x113) && !(val & 0x80)) @@ -788,6 +785,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val break; case 0x2a4: case 0x2a5: addr += 2; + /*FALLTHROUGH*/ case 0x2aa: case 0x2ab: WRITE8(addr, mach64->sc_left_right, val); break; @@ -797,6 +795,7 @@ static void mach64_accel_write_fifo(mach64_t *mach64, uint32_t addr, uint8_t val break; case 0x2b0: case 0x2b1: addr += 2; + /*FALLTHROUGH*/ case 0x2b6: case 0x2b7: WRITE8(addr, mach64->sc_top_bottom, val); break; @@ -1714,7 +1713,6 @@ static void mach64_vblank_start(svga_t *svga) uint8_t mach64_ext_readb(uint32_t addr, void *p) { mach64_t *mach64 = (mach64_t *)p; - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; uint8_t ret; if (!(addr & 0x400)) @@ -1840,9 +1838,9 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) case 0xc0: case 0xc1: case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), ramdac, &mach64->svga); + ret = ati68860_ramdac_in((addr & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); else - ret = ati68860_ramdac_in(addr & 3, ramdac, &mach64->svga); + ret = ati68860_ramdac_in(addr & 3, mach64->svga.ramdac, &mach64->svga); break; case 0xc4: case 0xc5: case 0xc6: case 0xc7: if (mach64->type == MACH64_VT2) @@ -1886,6 +1884,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x110: case 0x111: addr += 2; + /*FALLTHROUGH*/ case 0x114: case 0x115: case 0x118: case 0x119: case 0x11a: case 0x11b: case 0x11e: case 0x11f: @@ -1993,6 +1992,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x2a4: case 0x2a5: addr += 2; + /*FALLTHROUGH*/ case 0x2aa: case 0x2ab: mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_left_right); @@ -2004,6 +2004,7 @@ uint8_t mach64_ext_readb(uint32_t addr, void *p) break; case 0x2b0: case 0x2b1: addr += 2; + /*FALLTHROUGH*/ case 0x2b6: case 0x2b7: mach64_wait_fifo_idle(mach64); READ8(addr, mach64->sc_top_bottom); @@ -2136,8 +2137,6 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; svga_t *svga = &mach64->svga; - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; - ics2595_t *clock_gen = (ics2595_t *) svga->clock_gen; mach64_log("mach64_ext_writeb : addr %08X val %02X\n", addr, val); @@ -2254,12 +2253,12 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0x60: case 0x61: case 0x62: case 0x63: WRITE8(addr, mach64->cur_clr0, val); if (mach64->type == MACH64_VT2) - ramdac->pallook[0] = makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff); + ati68860_ramdac_set_pallook(mach64->svga.ramdac, 0, makecol32((mach64->cur_clr0 >> 24) & 0xff, (mach64->cur_clr0 >> 16) & 0xff, (mach64->cur_clr0 >> 8) & 0xff)); break; case 0x64: case 0x65: case 0x66: case 0x67: WRITE8(addr, mach64->cur_clr1, val); if (mach64->type == MACH64_VT2) - ramdac->pallook[1] = makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff); + ati68860_ramdac_set_pallook(mach64->svga.ramdac, 1, makecol32((mach64->cur_clr1 >> 24) & 0xff, (mach64->cur_clr1 >> 16) & 0xff, (mach64->cur_clr1 >> 8) & 0xff)); break; case 0x68: case 0x69: case 0x6a: case 0x6b: WRITE8(addr, mach64->cur_offset, val); @@ -2289,11 +2288,11 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0x90: case 0x91: case 0x92: case 0x93: WRITE8(addr, mach64->clock_cntl, val); if (mach64->type == MACH64_GX) - ics2595_write(clock_gen, val & 0x40, val & 0xf); + ics2595_write(svga->clock_gen, val & 0x40, val & 0xf); else { pll_write(mach64, addr, val); - clock_gen->output_clock = mach64->pll_freq[mach64->clock_cntl & 3]; + ics2595_setclock(svga->clock_gen, mach64->pll_freq[mach64->clock_cntl & 3]); } svga_recalctimings(&mach64->svga); break; @@ -2321,14 +2320,14 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *p) case 0xc0: case 0xc1: case 0xc2: case 0xc3: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, ramdac, &mach64->svga); + ati68860_ramdac_out((addr & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); else - ati68860_ramdac_out(addr & 3, val, ramdac, &mach64->svga); + ati68860_ramdac_out(addr & 3, val, mach64->svga.ramdac, &mach64->svga); break; case 0xc4: case 0xc5: case 0xc6: case 0xc7: WRITE8(addr, mach64->dac_cntl, val); svga_set_ramdac_type(svga, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); - ati68860_set_ramdac_type(ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); + ati68860_set_ramdac_type(mach64->svga.ramdac, (mach64->dac_cntl & 0x100) ? RAMDAC_8BIT : RAMDAC_6BIT); break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: @@ -2401,7 +2400,6 @@ void mach64_ext_writel(uint32_t addr, uint32_t val, void *p) uint8_t mach64_ext_inb(uint16_t port, void *p) { mach64_t *mach64 = (mach64_t *)p; - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; uint8_t ret; switch (port) @@ -2488,9 +2486,9 @@ uint8_t mach64_ext_inb(uint16_t port, void *p) case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), ramdac, &mach64->svga); + ret = ati68860_ramdac_in((port & 3) | ((mach64->dac_cntl & 3) << 2), mach64->svga.ramdac, &mach64->svga); else - ret = ati68860_ramdac_in(port & 3, ramdac, &mach64->svga); + ret = ati68860_ramdac_in(port & 3, mach64->svga.ramdac, &mach64->svga); break; case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: @@ -2558,7 +2556,6 @@ uint32_t mach64_ext_inl(uint16_t port, void *p) void mach64_ext_outb(uint16_t port, uint8_t val, void *p) { mach64_t *mach64 = (mach64_t *)p; - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) mach64->svga.ramdac; mach64_log("mach64_ext_outb : port %04X val %02X\n", port, val); switch (port) @@ -2641,9 +2638,9 @@ void mach64_ext_outb(uint16_t port, uint8_t val, void *p) case 0x5eec: case 0x5eed: case 0x5eee: case 0x5eef: if (mach64->type == MACH64_GX) - ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, ramdac, &mach64->svga); + ati68860_ramdac_out((port & 3) | ((mach64->dac_cntl & 3) << 2), val, mach64->svga.ramdac, &mach64->svga); else - ati68860_ramdac_out(port & 3, val, ramdac, &mach64->svga); + ati68860_ramdac_out(port & 3, val, mach64->svga.ramdac, &mach64->svga); break; case 0x62ec: case 0x62ed: case 0x62ee: case 0x62ef: @@ -2783,34 +2780,6 @@ uint32_t mach64_readl(uint32_t addr, void *p) return svga_readl_linear(addr, svga); } -void mach64_hwcursor_draw(svga_t *svga, int displine) -{ - ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac; - int x, offset; - uint8_t dat; - uint32_t col0 = ramdac->pallook[0]; - uint32_t col1 = ramdac->pallook[1]; - - offset = svga->hwcursor_latch.xoff; - for (x = 0; x < 64 - svga->hwcursor_latch.xoff; x += 4) - { - dat = svga->vram[svga->hwcursor_latch.addr + (offset >> 2)]; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 1] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 2] ^= 0xFFFFFF; - dat >>= 2; - if (!(dat & 2)) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] = (dat & 1) ? col1 : col0; - else if ((dat & 3) == 3) buffer32->line[displine][svga->hwcursor_latch.x + x + svga->x_add + 3] ^= 0xFFFFFF; - dat >>= 2; - offset += 4; - } - svga->hwcursor_latch.addr += 16; -} #define CLAMP(x) do \ { \ @@ -3300,7 +3269,7 @@ static void *mach64_common_init(const device_t *info) svga_init(&mach64->svga, mach64, mach64->vram_size << 20, mach64_recalctimings, mach64_in, mach64_out, - mach64_hwcursor_draw, + NULL, mach64_overlay_draw); if (info->flags & DEVICE_PCI) @@ -3325,6 +3294,8 @@ static void *mach64_common_init(const device_t *info) mach64->pci_regs[0x33] = 0x00; mach64->svga.ramdac = device_add(&ati68860_ramdac_device); + mach64->svga.dac_hwcursor_draw = ati68860_hwcursor_draw; + mach64->svga.clock_gen = device_add(&ics2595_device); mach64->dst_cntl = 3; diff --git a/src/video/vid_ati_mach64.h b/src/video/vid_ati_mach64.h deleted file mode 100644 index c44444d7a..000000000 --- a/src/video/vid_ati_mach64.h +++ /dev/null @@ -1,22 +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. - * - * ATi Mach64 graphics card emulation. - * - * Version: @(#)vid_ati_mach64.h 1.0.2 2018/03/18 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ - -extern const device_t mach64gx_isa_device; -extern const device_t mach64gx_vlb_device; -extern const device_t mach64gx_pci_device; -extern const device_t mach64vt2_device; diff --git a/src/video/vid_att20c49x_ramdac.c b/src/video/vid_att20c49x_ramdac.c index 1077c7e54..bce0a21c9 100644 --- a/src/video/vid_att20c49x_ramdac.c +++ b/src/video/vid_att20c49x_ramdac.c @@ -21,13 +21,21 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_att20c49x_ramdac.h" + + +typedef struct +{ + int type; + int state; + uint8_t ctrl; +} att49x_ramdac_t; + enum { @@ -35,9 +43,12 @@ enum ATT_492_3 }; + void -att49x_ramdac_out(uint16_t addr, uint8_t val, att49x_ramdac_t *ramdac, svga_t *svga) +att49x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) { + att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p; + switch (addr) { case 0x3C6: if (ramdac->state == 4) { @@ -93,10 +104,10 @@ att49x_ramdac_out(uint16_t addr, uint8_t val, att49x_ramdac_t *ramdac, svga_t *s uint8_t -att49x_ramdac_in(uint16_t addr, att49x_ramdac_t *ramdac, svga_t *svga) +att49x_ramdac_in(uint16_t addr, void *p, svga_t *svga) { - uint8_t temp; - temp = svga_in(addr, svga); + att49x_ramdac_t *ramdac = (att49x_ramdac_t *) p; + uint8_t temp = svga_in(addr, svga); switch (addr) { case 0x3C6: diff --git a/src/video/vid_att20c49x_ramdac.h b/src/video/vid_att20c49x_ramdac.h deleted file mode 100644 index 2a191afcf..000000000 --- a/src/video/vid_att20c49x_ramdac.h +++ /dev/null @@ -1,32 +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. - * - * Header of the emulation of a Sierra SC1502X RAMDAC. - * - * Used by the TLIVESA1 driver for ET4000. - * - * Version: @(#)vid_sc1502x_ramdac.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct -{ - int type; - int state; - uint8_t ctrl; -} att49x_ramdac_t; - -extern void att49x_ramdac_out(uint16_t addr, uint8_t val, att49x_ramdac_t *ramdac, svga_t *svga); -extern uint8_t att49x_ramdac_in(uint16_t addr, att49x_ramdac_t *ramdac, svga_t *svga); - -extern const device_t att490_ramdac_device; -extern const device_t att492_ramdac_device; diff --git a/src/video/vid_av9194.c b/src/video/vid_av9194.c index ad3f706a1..bc48c08b7 100644 --- a/src/video/vid_av9194.c +++ b/src/video/vid_av9194.c @@ -21,9 +21,12 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "vid_av9194.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" +#include "video.h" +#include "vid_svga.h" float diff --git a/src/video/vid_av9194.h b/src/video/vid_av9194.h deleted file mode 100644 index 11760fe53..000000000 --- a/src/video/vid_av9194.h +++ /dev/null @@ -1,21 +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. - * - * AV9194 clock generator emulation. - * - * Used by the S3 86c801 (V7-Mirage) card. - * - * Version: @(#)vid_av9194.c 1.0.1 2019/01/12 - * - * Authors: Miran Grca, - * - * Copyright 2016-2018 Miran Grca. - */ -float av9194_getclock(int clock, void *p); - -extern const device_t av9194_device; diff --git a/src/video/vid_bt48x_ramdac.c b/src/video/vid_bt48x_ramdac.c index 53dec87a6..20baf13eb 100644 --- a/src/video/vid_bt48x_ramdac.c +++ b/src/video/vid_bt48x_ramdac.c @@ -22,13 +22,29 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_bt48x_ramdac.h" + + +typedef struct +{ + PALETTE extpal; + uint32_t extpallook[256]; + uint8_t cursor32_data[256]; + uint8_t cursor64_data[1024]; + int hwc_y, hwc_x; + uint8_t cmd_r0; + uint8_t cmd_r1; + uint8_t cmd_r2; + uint8_t cmd_r3; + uint8_t cmd_r4; + uint8_t status; + uint8_t type; +} bt48x_ramdac_t; enum { @@ -69,8 +85,9 @@ bt48x_set_bpp(bt48x_ramdac_t *ramdac, svga_t *svga) void -bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *ramdac, svga_t *svga) +bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga) { + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; uint32_t o32; uint8_t *cd; uint16_t index; @@ -209,8 +226,9 @@ bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *r uint8_t -bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t *svga) +bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga) { + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; uint8_t temp = 0xff; uint8_t *cd; uint16_t index; @@ -330,6 +348,17 @@ bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t } +void +bt48x_recalctimings(void *p, svga_t *svga) +{ + bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) p; + + svga->interlace = ramdac->cmd_r2 & 0x08; + if (ramdac->cmd_r3 & 0x08) + svga->hdisp *= 2; /* x2 clock multiplier */ +} + + void bt48x_hwcursor_draw(svga_t *svga, int displine) { diff --git a/src/video/vid_bt48x_ramdac.h b/src/video/vid_bt48x_ramdac.h deleted file mode 100644 index ce952e1e8..000000000 --- a/src/video/vid_bt48x_ramdac.h +++ /dev/null @@ -1,44 +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. - * - * Header of the emulation of the Brooktree BT484-BT485A - * true colour RAMDAC family. - * - * Version: @(#)vid_bt485_ramdac.h 1.0.5 2019/01/12 - * - * Authors: Miran Grca, - * TheCollector1995, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 TheCollector1995. - */ -typedef struct -{ - PALETTE extpal; - uint32_t extpallook[256]; - uint8_t cursor32_data[256]; - uint8_t cursor64_data[1024]; - int hwc_y, hwc_x; - uint8_t cmd_r0; - uint8_t cmd_r1; - uint8_t cmd_r2; - uint8_t cmd_r3; - uint8_t cmd_r4; - uint8_t status; - uint8_t type; -} bt48x_ramdac_t; - -extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt48x_ramdac_t *ramdac, svga_t *svga); -extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, bt48x_ramdac_t *ramdac, svga_t *svga); -extern void bt48x_hwcursor_draw(svga_t *svga, int displine); - -extern const device_t bt484_ramdac_device; -extern const device_t att20c504_ramdac_device; -extern const device_t bt485_ramdac_device; -extern const device_t att20c505_ramdac_device; -extern const device_t bt485a_ramdac_device; diff --git a/src/video/vid_cga.c b/src/video/vid_cga.c index 2cb05a1d2..91f04501b 100644 --- a/src/video/vid_cga.c +++ b/src/video/vid_cga.c @@ -22,14 +22,14 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" #include "vid_cga.h" #include "vid_cga_comp.h" diff --git a/src/video/vid_cga_comp.c b/src/video/vid_cga_comp.c index b5e87078f..0d4d5a0a5 100644 --- a/src/video/vid_cga_comp.c +++ b/src/video/vid_cga_comp.c @@ -23,9 +23,9 @@ #include #include #include -#include "../86box.h" -#include "../timer.h" -#include "../mem.h" +#include "86box.h" +#include "timer.h" +#include "mem.h" #include "vid_cga.h" #include "vid_cga_comp.h" diff --git a/src/video/vid_cl54xx.c b/src/video/vid_cl54xx.c index 0ca557bd8..4b3df6ddc 100644 --- a/src/video/vid_cl54xx.c +++ b/src/video/vid_cl54xx.c @@ -9,7 +9,7 @@ * Emulation of select Cirrus Logic cards (CL-GD 5428, * CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported). * - * Version: @(#)vid_cl_54xx.c 1.0.32 2020/01/11 + * Version: @(#)vid_cl_54xx.c 1.0.34 2020/03/23 * * Authors: TheCollector1995, * Miran Grca, @@ -23,23 +23,27 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "mca.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "device.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_cl54xx.h" + +#define BIOS_GD5402_PATH L"roms/video/cirruslogic/avga2.rom" +#define BIOS_GD5402_ONBOARD_PATH L"roms/video/machines/cbm_sl386sx25/Commodore386SX-25_AVGA2.bin" +#define BIOS_GD5420_PATH L"roms/video/cirruslogic/5420.vbi" #if defined(DEV_BRANCH) && defined(USE_CL5422) -#define BIOS_GD5420_PATH L"roms/video/cirruslogic/5420.vbi" #define BIOS_GD5422_PATH L"roms/video/cirruslogic/cl5422.bin" #endif + #define BIOS_GD5426_PATH L"roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin" #define BIOS_GD5428_ISA_PATH L"roms/video/cirruslogic/5428.bin" #define BIOS_GD5428_PATH L"roms/video/cirruslogic/vlbusjapan.BIN" @@ -124,6 +128,10 @@ #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 +#define CL_GD5428_SYSTEM_BUS_MCA 5 +#define CL_GD5428_SYSTEM_BUS_VESA 6 +#define CL_GD5428_SYSTEM_BUS_ISA 7 + #define CL_GD5429_SYSTEM_BUS_VESA 5 #define CL_GD5429_SYSTEM_BUS_ISA 7 @@ -176,7 +184,7 @@ typedef struct gd54xx_t int unlock_special; } blt; - int pci, vlb; + int pci, vlb, mca; int countminusone; uint8_t pci_regs[256]; @@ -185,6 +193,9 @@ typedef struct gd54xx_t uint8_t fc; /* Feature Connector */ int card; + + uint8_t pos_regs[8]; + svga_t *mb_vga; uint32_t lfb_base; @@ -687,10 +698,19 @@ gd54xx_in(uint16_t addr, void *p) case 0x17: ret = svga->gdcreg[0x17] & ~(7 << 3); if (svga->crtc[0x27] <= CIRRUS_ID_CLGD5429) { - if (gd54xx->vlb) - ret |= (CL_GD5429_SYSTEM_BUS_VESA << 3); - else - ret |= (CL_GD5429_SYSTEM_BUS_ISA << 3); + if (svga->crtc[0x27] == CIRRUS_ID_CLGD5428) { + if (gd54xx->vlb) + ret |= (CL_GD5428_SYSTEM_BUS_VESA << 3); + else if (gd54xx->mca) + ret |= (CL_GD5428_SYSTEM_BUS_MCA << 3); + else + ret |= (CL_GD5428_SYSTEM_BUS_ISA << 3); + } else { + if (gd54xx->vlb) + ret |= (CL_GD5429_SYSTEM_BUS_VESA << 3); + else + ret |= (CL_GD5429_SYSTEM_BUS_ISA << 3); + } } else { if (gd54xx->pci) ret |= (CL_GD543X_SYSTEM_BUS_PCI << 3); @@ -875,8 +895,14 @@ gd54xx_in(uint16_t addr, void *p) } else { if ((svga->gdcaddr < 2) && !gd54xx->unlocked) ret = (svga->gdcreg[svga->gdcaddr] & 0x0f); - else - ret = svga->gdcreg[svga->gdcaddr]; + else { + if (svga->gdcaddr == 0) + ret = gd543x_mmio_read(0xb8000, gd54xx); + else if (svga->gdcaddr == 1) + ret = gd543x_mmio_read(0xb8004, gd54xx); + else + ret = svga->gdcreg[svga->gdcaddr]; + } } break; case 0x3d4: @@ -890,7 +916,7 @@ gd54xx_in(uint16_t addr, void *p) !gd54xx->unlocked) ret = 0xff; else switch (svga->crtcreg) { - case 0x22: /*Graphis Data Latches Readback Register*/ + case 0x22: /*Graphics Data Latches Readback Register*/ /*Should this be & 7 if 8 byte latch is enabled? */ ret = svga->latch.b[svga->gdcreg[4] & 3]; break; @@ -956,8 +982,9 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) { svga_t *svga = &gd54xx->svga; uint32_t base, size; - - if (!(gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + + if ((gd54xx->pci && (!(gd54xx->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))) || + (gd54xx->mca && (!(gd54xx->pos_regs[2] & 1)))) { mem_mapping_disable(&svga->mapping); mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_disable(&gd54xx->mmio_mapping); @@ -990,7 +1017,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) } if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->seqregs[0x07] & 0x01) && - (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) { + (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { if (gd54xx->mmio_vram_overlap) { mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd54xx->mmio_mapping, 0xb8000, 0x08000); @@ -1013,7 +1040,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) size = 16 * 1024 * 1024; else size = 4 * 1024 * 1024; - } else { /*VLB*/ + } else { /*VLB/ISA/MCA*/ base = 128*1024*1024; if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5436) size = 16 * 1024 * 1024; @@ -1023,8 +1050,7 @@ gd543x_recalc_mapping(gd54xx_t *gd54xx) mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&gd54xx->linear_mapping, base, size); - if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5426) && - (svga->crtc[0x27] != CIRRUS_ID_CLGD5424)) { + if ((svga->seqregs[0x17] & CIRRUS_MMIO_ENABLE) && (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429)) { if (svga->seqregs[0x17] & CIRRUS_MMIO_USE_PCIADDR) mem_mapping_disable(&gd54xx->mmio_mapping); /* MMIO is handled in the linear read/write functions */ else @@ -1845,9 +1871,6 @@ gd54xx_writel_linear(uint32_t addr, uint32_t val, void *p) case 3: return; } - - if (svga->fast) - sub_cycles(video_timing_write_l); } else { switch(ap) { case 0: @@ -2891,6 +2914,33 @@ cl_pci_write(int func, int addr, uint8_t val, void *p) } } +static uint8_t +gd5428_mca_read(int port, void *p) +{ + gd54xx_t *gd54xx = (gd54xx_t *)p; + + return gd54xx->pos_regs[port & 7]; +} + +static void +gd5428_mca_write(int port, uint8_t val, void *p) +{ + gd54xx_t *gd54xx = (gd54xx_t *)p; + + if (port < 0x102) + return; + + gd54xx->pos_regs[port & 7] = val; + gd543x_recalc_mapping(gd54xx); +} + +static uint8_t +gd5428_mca_feedb(void *p) +{ + gd54xx_t *gd54xx = (gd54xx_t *)p; + + return gd54xx->pos_regs[2] & 1; +} static void *gd54xx_init(const device_t *info) @@ -2903,27 +2953,35 @@ static void memset(gd54xx, 0, sizeof(gd54xx_t)); gd54xx->pci = !!(info->flags & DEVICE_PCI); - gd54xx->vlb = !!(info->flags & DEVICE_VLB); + gd54xx->vlb = !!(info->flags & DEVICE_VLB); + gd54xx->mca = !!(info->flags & DEVICE_MCA); gd54xx->rev = 0; gd54xx->has_bios = 1; switch (id) { -#if defined(DEV_BRANCH) && defined(USE_CL5422) case CIRRUS_ID_CLGD5402: + if (info->local & 0x200) + romfn = BIOS_GD5402_ONBOARD_PATH; + else + romfn = BIOS_GD5402_PATH; + break; + case CIRRUS_ID_CLGD5420: romfn = BIOS_GD5420_PATH; break; + +#if defined(DEV_BRANCH) && defined(USE_CL5422) case CIRRUS_ID_CLGD5422: case CIRRUS_ID_CLGD5424: romfn = BIOS_GD5422_PATH; break; #endif - + case CIRRUS_ID_CLGD5426: romfn = BIOS_GD5426_PATH; break; - + case CIRRUS_ID_CLGD5428: if (gd54xx->vlb) romfn = BIOS_GD5428_PATH; @@ -2972,16 +3030,21 @@ static void romfn = BIOS_GD5480_PATH; break; } - - if (id >= CIRRUS_ID_CLGD5420) - vram = device_get_config_int("memory"); - else - vram = 0; - - if (vram) - gd54xx->vram_size = vram << 20; - else - gd54xx->vram_size = 1 << 19; + + if (info->flags & DEVICE_MCA) { + vram = 1; + gd54xx->vram_size = 1 << 20; + } else { + if (id >= CIRRUS_ID_CLGD5420) + vram = device_get_config_int("memory"); + else + vram = 0; + + if (vram) + gd54xx->vram_size = vram << 20; + else + gd54xx->vram_size = 1 << 19; + } gd54xx->vram_mask = gd54xx->vram_size - 1; @@ -3002,29 +3065,28 @@ static void mem_mapping_set_handler(&svga->mapping, gd54xx_read, gd54xx_readw, gd54xx_readl, gd54xx_write, gd54xx_writew, gd54xx_writel); mem_mapping_set_p(&svga->mapping, gd54xx); - + mem_mapping_add(&gd54xx->mmio_mapping, 0, 0, - gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, - gd543x_mmio_writeb, gd543x_mmio_writew, gd543x_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); + gd543x_mmio_read, gd543x_mmio_readw, gd543x_mmio_readl, + gd543x_mmio_writeb, gd543x_mmio_writew, gd543x_mmio_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); mem_mapping_disable(&gd54xx->mmio_mapping); mem_mapping_add(&gd54xx->linear_mapping, 0, 0, - gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, - gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); + gd54xx_readb_linear, gd54xx_readw_linear, gd54xx_readl_linear, + gd54xx_writeb_linear, gd54xx_writew_linear, gd54xx_writel_linear, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); mem_mapping_disable(&gd54xx->linear_mapping); mem_mapping_add(&gd54xx->aperture2_mapping, 0, 0, - gd5436_aperture2_readb, gd5436_aperture2_readw, gd5436_aperture2_readl, - gd5436_aperture2_writeb, gd5436_aperture2_writew, gd5436_aperture2_writel, - NULL, MEM_MAPPING_EXTERNAL, gd54xx); + gd5436_aperture2_readb, gd5436_aperture2_readw, gd5436_aperture2_readl, + gd5436_aperture2_writeb, gd5436_aperture2_writew, gd5436_aperture2_writel, + NULL, MEM_MAPPING_EXTERNAL, gd54xx); mem_mapping_disable(&gd54xx->aperture2_mapping); io_sethandler(0x03c0, 0x0020, gd54xx_in, NULL, NULL, gd54xx_out, NULL, NULL, gd54xx); - + svga->hwcursor.yoff = 32; svga->hwcursor.xoff = 0; -#if defined(DEV_BRANCH) && defined(USE_CL5422) if (id >= CIRRUS_ID_CLGD5420) { gd54xx->vclk_n[0] = 0x4a; gd54xx->vclk_d[0] = 0x2b; @@ -3044,16 +3106,6 @@ static void gd54xx->vclk_n[3] = 0x7e; gd54xx->vclk_d[3] = 0x33; } -#else - gd54xx->vclk_n[0] = 0x4a; - gd54xx->vclk_d[0] = 0x2b; - gd54xx->vclk_n[1] = 0x5b; - gd54xx->vclk_d[1] = 0x2f; - gd54xx->vclk_n[2] = 0x45; - gd54xx->vclk_d[2] = 0x30; - gd54xx->vclk_n[3] = 0x7e; - gd54xx->vclk_d[3] = 0x33; -#endif svga->extra_banks[1] = 0x8000; @@ -3072,16 +3124,28 @@ static void if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5429) gd54xx->unlocked = 1; + if (gd54xx->mca) { + gd54xx->pos_regs[0] = 0x7b; + gd54xx->pos_regs[1] = 0x91; + mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, gd54xx); + } + return gd54xx; } -#if defined(DEV_BRANCH) && defined(USE_CL5422) +static int +gd5402_available(void) +{ + return rom_present(BIOS_GD5402_PATH); +} + static int gd5420_available(void) { return rom_present(BIOS_GD5420_PATH); } +#if defined(DEV_BRANCH) && defined(USE_CL5422) static int gd5422_available(void) { @@ -3189,7 +3253,6 @@ gd54xx_force_redraw(void *p) gd54xx->svga.fullchange = changeframecount; } -#if defined(DEV_BRANCH) && defined(USE_CL5422) static const device_config_t gd5422_config[] = { { @@ -3210,7 +3273,6 @@ static const device_config_t gd5422_config[] = "","",-1 } }; -#endif static const device_config_t gd5428_config[] = { @@ -3293,7 +3355,6 @@ static const device_config_t gd5434_config[] = } }; -#if defined(DEV_BRANCH) && defined(USE_CL5422) const device_t gd5402_isa_device = { "Cirrus Logic GD-5402 (ACUMOS AVGA2)", @@ -3301,7 +3362,20 @@ const device_t gd5402_isa_device = CIRRUS_ID_CLGD5402, gd54xx_init, gd54xx_close, NULL, - gd5420_available, /* Common BIOS between 5402 and 5420 */ + gd5402_available, + gd54xx_speed_changed, + gd54xx_force_redraw, + NULL, +}; + +const device_t gd5402_onboard_device = +{ + "Cirrus Logic GD-5402 (ACUMOS AVGA2) (On-Board)", + DEVICE_AT | DEVICE_ISA, + CIRRUS_ID_CLGD5402 | 0x200, + gd54xx_init, gd54xx_close, + NULL, + NULL, gd54xx_speed_changed, gd54xx_force_redraw, NULL, @@ -3314,12 +3388,13 @@ const device_t gd5420_isa_device = CIRRUS_ID_CLGD5420, gd54xx_init, gd54xx_close, NULL, - gd5420_available, /* Common BIOS between 5402 and 5420 */ + gd5420_available, gd54xx_speed_changed, gd54xx_force_redraw, gd5422_config, }; +#if defined(DEV_BRANCH) && defined(USE_CL5422) const device_t gd5422_isa_device = { "Cirrus Logic GD-5422", DEVICE_AT | DEVICE_ISA, @@ -3387,6 +3462,20 @@ const device_t gd5428_vlb_device = gd5428_config }; +const device_t gd5428_mca_device = +{ + "Cirrus Logic CL-GD 5428 (IBM SVGA Adapter/A)", + DEVICE_MCA, + CIRRUS_ID_CLGD5428, + gd54xx_init, + gd54xx_close, + NULL, + gd5428_available, + gd54xx_speed_changed, + gd54xx_force_redraw, + NULL +}; + const device_t gd5429_isa_device = { "Cirrus Logic CL-GD 5429 (ISA)", diff --git a/src/video/vid_cl54xx.h b/src/video/vid_cl54xx.h deleted file mode 100644 index b777d28dc..000000000 --- a/src/video/vid_cl54xx.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#if defined(DEV_BRANCH) && defined(USE_CL5422) -extern const device_t gd5402_isa_device; -extern const device_t gd5420_isa_device; -extern const device_t gd5422_isa_device; -extern const device_t gd5424_vlb_device; -#endif -extern const device_t gd5426_vlb_device; -extern const device_t gd5428_isa_device; -extern const device_t gd5428_vlb_device; -extern const device_t gd5429_isa_device; -extern const device_t gd5429_vlb_device; -extern const device_t gd5430_vlb_device; -extern const device_t gd5430_pci_device; -extern const device_t gd5434_isa_device; -extern const device_t gd5434_vlb_device; -extern const device_t gd5434_pci_device; -extern const device_t gd5436_pci_device; -extern const device_t gd5440_onboard_pci_device; -extern const device_t gd5440_pci_device; -extern const device_t gd5446_pci_device; -extern const device_t gd5446_stb_pci_device; -extern const device_t gd5480_pci_device; \ No newline at end of file diff --git a/src/video/vid_colorplus.c b/src/video/vid_colorplus.c index 80393ecbb..93fad1cc8 100644 --- a/src/video/vid_colorplus.c +++ b/src/video/vid_colorplus.c @@ -22,14 +22,14 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../lpt.h" -#include "../pit.h" -#include "../mem.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "lpt.h" +#include "pit.h" +#include "mem.h" +#include "device.h" #include "video.h" #include "vid_cga.h" #include "vid_colorplus.h" diff --git a/src/video/vid_compaq_cga.c b/src/video/vid_compaq_cga.c index f17c526a1..d6bf29a72 100644 --- a/src/video/vid_compaq_cga.c +++ b/src/video/vid_compaq_cga.c @@ -24,14 +24,14 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" #include "vid_cga.h" #include "vid_cga_comp.h" diff --git a/src/video/vid_compaq_cga.h b/src/video/vid_compaq_cga.h deleted file mode 100644 index e6c684d52..000000000 --- a/src/video/vid_compaq_cga.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef VIDEO_COMPAQ_CGA_H -# define VIDEO_COMPAQ_CGA_H - - -#ifdef EMU_DEVICE_H -extern const device_t compaq_cga_device; -extern const device_t compaq_cga_2_device; -#endif - - -#endif /*VIDEO_COMPAQ_CGA_H*/ diff --git a/src/video/vid_ega.c b/src/video/vid_ega.c index acda3edde..0b8753bd1 100644 --- a/src/video/vid_ega.c +++ b/src/video/vid_ega.c @@ -9,7 +9,7 @@ * Emulation of the EGA and Chips & Technologies SuperEGA * graphics cards. * - * Version: @(#)vid_ega.c 1.0.23 2019/11/19 + * Version: @(#)vid_ega.c 1.0.24 2019/11/20 * * Authors: Sarah Walker, * Miran Grca, @@ -22,31 +22,33 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" +#include "vid_ati_eeprom.h" #include "vid_ega.h" -#include "vid_ega_render.h" void ega_doblit(int y1, int y2, int wx, int wy, ega_t *ega); -#define BIOS_IBM_PATH L"roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" -#define BIOS_CPQ_PATH L"roms/video/ega/108281-001.bin" -#define BIOS_SEGA_PATH L"roms/video/ega/lega.vbi" +#define BIOS_IBM_PATH L"roms/video/ega/ibm_6277356_ega_card_u44_27128.bin" +#define BIOS_CPQ_PATH L"roms/video/ega/108281-001.bin" +#define BIOS_SEGA_PATH L"roms/video/ega/lega.vbi" +#define BIOS_ATIEGA_PATH L"roms/video/ega/ATI EGA Wonder 800+ N1.00.BIN" enum { EGA_IBM = 0, EGA_COMPAQ, - EGA_SUPEREGA + EGA_SUPEREGA, + EGA_ATI }; @@ -74,6 +76,30 @@ ega_out(uint16_t addr, uint8_t val, void *p) addr ^= 0x60; switch (addr) { + case 0x1ce: + ega->index = val; + break; + case 0x1cf: + ega->regs[ega->index] = val; + switch (ega->index) { + case 0xb0: + ega_recalctimings(ega); + break; + case 0xb2: case 0xbe: +#if 0 + if (ega->regs[0xbe] & 8) { /*Read/write bank mode*/ + svga->read_bank = ((ega->regs[0xb2] >> 5) & 7) * 0x10000; + svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; + } else /*Single bank mode*/ + svga->read_bank = svga->write_bank = ((ega->regs[0xb2] >> 1) & 7) * 0x10000; +#endif + break; + case 0xb3: + ati_eeprom_write((ati_eeprom_t *) ega->eeprom, val & 8, val & 2, val & 1); + break; + } + break; + case 0x3c0: case 0x3c1: if (!ega->attrff) { ega->attraddr = val & 31; @@ -211,6 +237,22 @@ uint8_t ega_in(uint16_t addr, void *p) addr ^= 0x60; switch (addr) { + case 0x1ce: + ret = ega->index; + break; + case 0x1cf: + switch (ega->index) { + case 0xb7: + ret = ega->regs[ega->index] & ~8; + if (ati_eeprom_read((ati_eeprom_t *) ega->eeprom)) + ret |= 8; + break; + default: + ret = ega->regs[ega->index]; + break; + } + break; + case 0x3c0: ret = ega->attraddr | ega->attr_palette_enable; break; @@ -259,6 +301,8 @@ uint8_t ega_in(uint16_t addr, void *p) void ega_recalctimings(ega_t *ega) { + int clksel; + double _dispontime, _dispofftime, disptime; double crtcconst; @@ -291,8 +335,35 @@ ega_recalctimings(ega_t *ega) ega->linedbl = ega->crtc[9] & 0x80; ega->rowcount = ega->crtc[9] & 0x1f; - if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); - else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); + if (ega->eeprom) { + clksel = ((ega->miscout & 0xc) >> 2) | ((ega->regs[0xbe] & 0x10) ? 4 : 0); + + switch (clksel) { + case 0: + crtcconst = (cpuclock / 25175000.0 * (double)(1ull << 32)); + break; + case 1: + crtcconst = (cpuclock / 28322000.0 * (double)(1ull << 32)); + break; + case 4: + crtcconst = (cpuclock / 14318181.0 * (double)(1ull << 32)); + break; + case 5: + crtcconst = (cpuclock / 16257000.0 * (double)(1ull << 32)); + break; + case 7: + default: + crtcconst = (cpuclock / 36000000.0 * (double)(1ull << 32)); + break; + } + if (!(ega->seqregs[1] & 1)) + crtcconst *= 9.0; + else + crtcconst *= 8.0; + } else { + if (ega->vidclock) crtcconst = (ega->seqregs[1] & 1) ? MDACONST : (MDACONST * (9.0 / 8.0)); + else crtcconst = (ega->seqregs[1] & 1) ? CGACONST : (CGACONST * (9.0 / 8.0)); + } ega->interlace = 0; @@ -353,11 +424,15 @@ ega_recalctimings(ega_t *ega) _dispontime = (double) (ega->crtc[1] + 1); } _dispofftime = disptime - _dispontime; - _dispontime = _dispontime * crtcconst; - _dispofftime = _dispofftime * crtcconst; + _dispontime *= crtcconst; + _dispofftime *= crtcconst; ega->dispontime = (uint64_t)(_dispontime); ega->dispofftime = (uint64_t)(_dispofftime); + if (ega->dispontime < TIMER_USEC) + ega->dispontime = TIMER_USEC; + if (ega->dispofftime < TIMER_USEC) + ega->dispofftime = TIMER_USEC; } @@ -399,9 +474,13 @@ ega_poll(void *p) ega->displine++; ega->ma = old_ma; - ega_render_overscan_left(ega); + ega->render(ega); + + ega->x_add = (overscan_x >> 1); + ega_render_overscan_left(ega); ega_render_overscan_right(ega); + ega->x_add = (overscan_x >> 1) - ega->scrollcache; ega->y_add >>= 1; ega->displine >>= 1; @@ -949,6 +1028,10 @@ ega_standalone_init(const device_t *info) rom_init(&ega->bios_rom, BIOS_SEGA_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); break; + case EGA_ATI: + rom_init(&ega->bios_rom, BIOS_ATIEGA_PATH, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + break; } if ((ega->bios_rom.rom[0x3ffe] == 0xaa) && (ega->bios_rom.rom[0x3fff] == 0x55)) { @@ -968,6 +1051,13 @@ ega_standalone_init(const device_t *info) mem_mapping_add(&ega->mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, ega); io_sethandler(0x03a0, 0x0040, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + if (info->local == EGA_ATI) { + io_sethandler(0x01ce, 0x0002, ega_in, NULL, NULL, ega_out, NULL, NULL, ega); + ega->eeprom = malloc(sizeof(ati_eeprom_t)); + memset(ega->eeprom, 0, sizeof(ati_eeprom_t)); + ati_eeprom_load((ati_eeprom_t *) ega->eeprom, L"egawonder800.nvr", 0); + } + return ega; } @@ -993,11 +1083,20 @@ sega_standalone_available(void) } +static int +atiega_standalone_available(void) +{ + return rom_present(BIOS_ATIEGA_PATH); +} + + static void ega_close(void *p) { ega_t *ega = (ega_t *)p; + if (ega->eeprom) + free(ega->eeprom); free(ega->vram); free(ega); } @@ -1121,3 +1220,15 @@ const device_t sega_device = NULL, ega_config }; + +const device_t atiega_device = +{ + "ATI EGA Wonder 800+", + DEVICE_ISA, + EGA_ATI, + ega_standalone_init, ega_close, NULL, + atiega_standalone_available, + ega_speed_changed, + NULL, + ega_config +}; diff --git a/src/video/vid_ega.h b/src/video/vid_ega.h index f64da0a01..170a91090 100644 --- a/src/video/vid_ega.h +++ b/src/video/vid_ega.h @@ -9,13 +9,13 @@ * Emulation of the EGA and Chips & Technologies SuperEGA * graphics cards. * - * Version: @(#)vid_ega.h 1.0.8 2019/10/03 + * Version: @(#)vid_ega.h 1.0.9 2020/01/20 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #ifndef VIDEO_EGA_H # define VIDEO_EGA_H @@ -37,6 +37,7 @@ typedef struct ega_t { uint8_t attrregs[32]; uint8_t seqregs[64]; uint8_t egapal[16]; + uint8_t regs[256]; uint8_t *vram; @@ -51,7 +52,7 @@ typedef struct ega_t { hdisp, hdisp_old, htotal, hdisp_time, rowoffset, vblankstart, scrollcache, firstline, lastline, firstline_draw, lastline_draw, x_add, y_add, - displine, video_res_x, video_res_y, video_bpp; + displine, video_res_x, video_res_y, video_bpp, index; uint32_t charseta, charsetb, ma_latch, ma, maback, ca, vram_limit, overscan_color; @@ -64,6 +65,8 @@ typedef struct ega_t { double clock; void (*render)(struct ega_t *svga); + + void *eeprom; } ega_t; #endif @@ -72,6 +75,7 @@ typedef struct ega_t { extern const device_t ega_device; extern const device_t cpqega_device; extern const device_t sega_device; +extern const device_t atiega_device; #endif extern int update_overscan; @@ -96,4 +100,32 @@ extern void ega_write(uint32_t addr, uint8_t val, void *p); extern uint8_t ega_read(uint32_t addr, void *p); +extern int firstline_draw, lastline_draw; +extern int displine; +extern int sc; + +extern uint32_t ma, ca; +extern int con, cursoron, cgablink; + +extern int scrollcache; + +extern uint8_t edatlookup[4][4]; + +#if defined(EMU_MEM_H) && defined(EMU_ROM_H) +void ega_render_blank(ega_t *ega); + +void ega_render_overscan_left(ega_t *ega); +void ega_render_overscan_right(ega_t *ega); + +void ega_render_text_40(ega_t *ega); +void ega_render_text_80(ega_t *ega); + +void ega_render_2bpp_lowres(ega_t *ega); +void ega_render_2bpp_highres(ega_t *ega); + +void ega_render_4bpp_lowres(ega_t *ega); +void ega_render_4bpp_highres(ega_t *ega); +#endif + + #endif /*VIDEO_EGA_H*/ diff --git a/src/video/vid_ega_render.c b/src/video/vid_ega_render.c index cf5ec7d50..471d3c531 100644 --- a/src/video/vid_ega_render.c +++ b/src/video/vid_ega_render.c @@ -20,14 +20,13 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" #include "video.h" #include "vid_ega.h" -#include "vid_ega_render.h" int diff --git a/src/video/vid_ega_render.h b/src/video/vid_ega_render.h deleted file mode 100644 index a905fc5dd..000000000 --- a/src/video/vid_ega_render.h +++ /dev/null @@ -1,42 +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. - * - * EGA renderers. - * - * Version: @(#)vid_ega_render.h 1.0.3 2019/10/03 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ - -extern int firstline_draw, lastline_draw; -extern int displine; -extern int sc; - -extern uint32_t ma, ca; -extern int con, cursoron, cgablink; - -extern int scrollcache; - -extern uint8_t edatlookup[4][4]; - -void ega_render_blank(ega_t *ega); - -void ega_render_overscan_left(ega_t *ega); -void ega_render_overscan_right(ega_t *ega); - -void ega_render_text_40(ega_t *ega); -void ega_render_text_80(ega_t *ega); - -void ega_render_2bpp_lowres(ega_t *ega); -void ega_render_2bpp_highres(ega_t *ega); - -void ega_render_4bpp_lowres(ega_t *ega); -void ega_render_4bpp_highres(ega_t *ega); diff --git a/src/video/vid_et4000.c b/src/video/vid_et4000.c index 3702098df..ad4bd13a9 100644 --- a/src/video/vid_et4000.c +++ b/src/video/vid_et4000.c @@ -8,7 +8,7 @@ * * Emulation of the Tseng Labs ET4000. * - * Version: @(#)vid_et4000.c 1.0.20 2018/10/04 + * Version: @(#)vid_et4000.c 1.0.20 2018/10/04e * * Authors: Fred N. van Kempen, * Miran Grca, @@ -42,18 +42,16 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "86box_io.h" +#include "mca.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_sc1502x_ramdac.h" -#include "vid_et4000.h" #define BIOS_ROM_PATH L"roms/video/et4000/et4000.bin" diff --git a/src/video/vid_et4000.h b/src/video/vid_et4000.h deleted file mode 100644 index b0a566c61..000000000 --- a/src/video/vid_et4000.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Emulation of the Tseng Labs ET4000. - * - * Version: @(#)vid_et4000.c 1.0.9 2018/08/16 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#ifndef EMU_VID_ET4000_H -# define EMU_VID_ET4000_H - -extern const device_t et4000_isa_device; -extern const device_t et4000k_isa_device; -extern const device_t et4000k_tg286_isa_device; -extern const device_t et4000_mca_device; - -#endif /*EMU_VID_ET4000_H*/ \ No newline at end of file diff --git a/src/video/vid_et4000w32.c b/src/video/vid_et4000w32.c index 66250d248..ccd8a6aee 100644 --- a/src/video/vid_et4000w32.c +++ b/src/video/vid_et4000w32.c @@ -25,19 +25,17 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "device.h" +#include "timer.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_icd2061.h" -#include "vid_stg_ramdac.h" #define BIOS_ROM_PATH_DIAMOND L"roms/video/et4000w32/et4000w32.bin" @@ -257,7 +255,7 @@ void et4000w32p_out(uint16_t addr, uint8_t val, void *p) if (et4000->pci) { et4000->linearbase &= 0xc0000000; - et4000->linearbase = (val & 0xfc) << 22; + et4000->linearbase |= (val & 0xfc) << 22; } else { @@ -1247,9 +1245,9 @@ void et4000w32p_pci_write(int func, int addr, uint8_t val, void *p) case 0x13: et4000->linearbase &= 0x00c00000; - et4000->linearbase = (et4000->pci_regs[0x13] << 24); + et4000->linearbase |= (et4000->pci_regs[0x13] << 24); svga->crtc[0x30] &= 3; - svga->crtc[0x30] = ((et4000->linearbase & 0x3f000000) >> 22); + svga->crtc[0x30] |= ((et4000->linearbase & 0x3f000000) >> 22); et4000w32p_recalcmapping(et4000); break; diff --git a/src/video/vid_et4000w32.h b/src/video/vid_et4000w32.h deleted file mode 100644 index 350933be5..000000000 --- a/src/video/vid_et4000w32.h +++ /dev/null @@ -1,5 +0,0 @@ -extern const device_t et4000w32p_vlb_device; -extern const device_t et4000w32p_pci_device; - -extern const device_t et4000w32p_cardex_vlb_device; -extern const device_t et4000w32p_cardex_pci_device; diff --git a/src/video/vid_genius.c b/src/video/vid_genius.c index 89f40da8c..9f76ada3e 100644 --- a/src/video/vid_genius.c +++ b/src/video/vid_genius.c @@ -21,17 +21,16 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../plat.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "plat.h" #include "video.h" -#include "vid_genius.h" #define BIOS_ROM_PATH L"roms/video/genius/8x12.bin" diff --git a/src/video/vid_genius.h b/src/video/vid_genius.h deleted file mode 100644 index e1388ec5c..000000000 --- a/src/video/vid_genius.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t genius_device; diff --git a/src/video/vid_hercules.c b/src/video/vid_hercules.c index fd3c85284..15538431f 100644 --- a/src/video/vid_hercules.c +++ b/src/video/vid_hercules.c @@ -21,17 +21,16 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../mem.h" -#include "../rom.h" -#include "../io.h" -#include "../timer.h" -#include "../lpt.h" -#include "../pit.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "mem.h" +#include "rom.h" +#include "86box_io.h" +#include "timer.h" +#include "lpt.h" +#include "pit.h" +#include "device.h" #include "video.h" -#include "vid_hercules.h" typedef struct { diff --git a/src/video/vid_hercules.h b/src/video/vid_hercules.h deleted file mode 100644 index 3c145e18f..000000000 --- a/src/video/vid_hercules.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t hercules_device; diff --git a/src/video/vid_herculesplus.c b/src/video/vid_herculesplus.c index 2a4497bce..fc4f0ad97 100644 --- a/src/video/vid_herculesplus.c +++ b/src/video/vid_herculesplus.c @@ -21,16 +21,15 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../lpt.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "lpt.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" -#include "vid_herculesplus.h" /* extended CRTC registers */ diff --git a/src/video/vid_herculesplus.h b/src/video/vid_herculesplus.h deleted file mode 100644 index 72b47c35f..000000000 --- a/src/video/vid_herculesplus.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: John Elliott - see COPYING for more details -*/ -extern const device_t herculesplus_device; diff --git a/src/video/vid_ht216.c b/src/video/vid_ht216.c index a0479a696..bb7be328c 100644 --- a/src/video/vid_ht216.c +++ b/src/video/vid_ht216.c @@ -21,18 +21,17 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../timer.h" -#include "../pic.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "mem.h" +#include "timer.h" +#include "pic.h" +#include "rom.h" +#include "device.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_ht216.h" typedef struct ht216_t diff --git a/src/video/vid_icd2061.c b/src/video/vid_icd2061.c index 1c1746df5..7dbe9d3ca 100644 --- a/src/video/vid_icd2061.c +++ b/src/video/vid_icd2061.c @@ -25,9 +25,18 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "vid_icd2061.h" +#include "86box.h" +#include "device.h" + + +typedef struct icd2061_t +{ + float freq[3]; + + int count, bit_count, + unlocked, state; + uint32_t data, ctrl; +} icd2061_t; #ifdef ENABLE_ICD2061_LOG @@ -51,10 +60,12 @@ icd2061_log(const char *fmt, ...) void -icd2061_write(icd2061_t *icd2061, int val) +icd2061_write(void *p, int val) { + icd2061_t *icd2061 = (icd2061_t *) p; + int nd, oc, nc; - int a, qa, q, pa, p, m, ps; + int a, qa, q, pa, p_, m, ps; nd = (val & 2) >> 1; /* Old data. */ oc = icd2061->state & 1; /* Old clock. */ @@ -96,14 +107,14 @@ icd2061_write(icd2061_t *icd2061, int val) m = ((icd2061->data >> 8) & 0x07); /* M (ICD2061) / R (ICS9161) */ qa = ((icd2061->data >> 1) & 0x7f); /* Q' (ICD2061) / M' (ICS9161) */ - p = pa + 3; /* P (ICD2061) / N (ICS9161) */ + p_ = pa + 3; /* P (ICD2061) / N (ICS9161) */ m = 1 << m; q = qa + 2; /* Q (ICD2061) / M (ICS9161) */ ps = (icd2061->ctrl & (1 << a)) ? 4 : 2; /* Prescale */ - icd2061->freq[a] = ((float)(p * ps) / (float)(q * m)) * 14318184.0f; + icd2061->freq[a] = ((float)(p_ * ps) / (float)(q * m)) * 14318184.0f; - icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p, m, q, a, icd2061->freq[a]); + icd2061_log("P = %02X, M = %01X, Q = %02X, freq[%i] = %f\n", p_, m, q, a, icd2061->freq[a]); } else if (a == 6) { icd2061->ctrl = ((icd2061->data >> 13) & 0xff); icd2061_log("ctrl = %02X\n", icd2061->ctrl); diff --git a/src/video/vid_icd2061.h b/src/video/vid_icd2061.h deleted file mode 100644 index 5b1c853e3..000000000 --- a/src/video/vid_icd2061.h +++ /dev/null @@ -1,40 +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. - * - * ICD2061 clock generator emulation header. - * Also emulates the ICS9161 which is the same as the ICD2016, - * but without the need for tuning (which is irrelevant in - * emulation anyway). - * - * Used by ET4000w32/p (Diamond Stealth 32) and the S3 - * Vision964 family. - * - * Version: @(#)vid_icd2061.h 1.0.3 2018/10/04 - * - * Authors: Miran Grca, - * - * Copyright 2018 Miran Grca. - */ -typedef struct icd2061_t -{ - float freq[3]; - - int count, bit_count; - int unlocked, state; - uint32_t data, ctrl; -} icd2061_t; - -void icd2061_write(icd2061_t *icd2061, int val); -float icd2061_getclock(int clock, void *p); - -extern const device_t icd2061_device; -extern const device_t ics9161_device; - -/* The code is the same, the #define's are so that the correct name can be used. */ -#define ics9161_write icd2061_write -#define ics9161_getclock icd2061_getclock diff --git a/src/video/vid_ics2595.c b/src/video/vid_ics2595.c index 711fb4641..374dda318 100644 --- a/src/video/vid_ics2595.c +++ b/src/video/vid_ics2595.c @@ -21,9 +21,19 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "vid_ics2595.h" +#include "86box.h" +#include "device.h" + + +typedef struct ics2595_t +{ + int oldfs3, oldfs2; + int dat; + int pos, state; + + double clocks[16]; + double output_clock; +} ics2595_t; enum @@ -38,9 +48,11 @@ static int ics2595_div[4] = {8, 4, 2, 1}; void -ics2595_write(ics2595_t *ics2595, int strobe, int dat) +ics2595_write(void *p, int strobe, int dat) { - int d, n, l; + ics2595_t *ics2595 = (ics2595_t *) p; + int d, n; + int l; if (strobe) { if ((dat & 8) && !ics2595->oldfs3) { /*Data clock*/ @@ -94,6 +106,24 @@ ics2595_close(void *priv) } +double +ics2595_getclock(void *p) +{ + ics2595_t *ics2595 = (ics2595_t *) p; + + return ics2595->output_clock; +} + + +void +ics2595_setclock(void *p, double clock) +{ + ics2595_t *ics2595 = (ics2595_t *) p; + + ics2595->output_clock = clock; +} + + const device_t ics2595_device = { "ICS2595 clock chip", diff --git a/src/video/vid_ics2595.h b/src/video/vid_ics2595.h deleted file mode 100644 index 1453a38ba..000000000 --- a/src/video/vid_ics2595.h +++ /dev/null @@ -1,31 +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. - * - * ICS2595 clock chip emulation header. Used by ATI Mach64. - * - * Version: @(#)vid_ics2595.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct ics2595_t -{ - int oldfs3, oldfs2; - int dat; - int pos, state; - - double clocks[16]; - double output_clock; -} ics2595_t; - -extern void ics2595_write(ics2595_t *ics2595, int strobe, int dat); - -extern const device_t ics2595_device; diff --git a/src/video/vid_im1024.c b/src/video/vid_im1024.c index 0a8ca6e6c..301c0fd6e 100644 --- a/src/video/vid_im1024.c +++ b/src/video/vid_im1024.c @@ -54,17 +54,16 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../pit.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "timer.h" +#include "device.h" +#include "pit.h" +#include "plat.h" #include "video.h" #include "vid_pgc.h" -#include "vid_im1024.h" #define BIOS_ROM_PATH L"roms/video/im1024/im1024font.bin" @@ -523,11 +522,21 @@ hndl_poly(pgc_t *pgc) #ifdef ENABLE_IM1024_LOG im1024_log("IM1024: POLY: out of memory\n"); #endif + if (x) + free(x); + if (y) + free(y); return; } while (parsing) { - if (! pgc_param_byte(pgc, &count)) return; + if (! pgc_param_byte(pgc, &count)) { + if (x) + free(x); + if (y) + free(y); + return; + } if (count + realcount >= as) { nx = (int32_t *)realloc(x, 2 * as * sizeof(int32_t)); @@ -544,8 +553,20 @@ hndl_poly(pgc_t *pgc) } for (n = 0; n < count; n++) { - if (! pgc_param_word(pgc, &xw)) return; - if (! pgc_param_word(pgc, &yw)) return; + if (! pgc_param_word(pgc, &xw)) { + if (x) + free(x); + if (y) + free(y); + return; + } + if (! pgc_param_word(pgc, &yw)) { + if (x) + free(x); + if (y) + free(y); + return; + } /* Skip degenerate line segments. */ if (realcount > 0 && diff --git a/src/video/vid_im1024.h b/src/video/vid_im1024.h deleted file mode 100644 index bf716b1d3..000000000 --- a/src/video/vid_im1024.h +++ /dev/null @@ -1,18 +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. - * - * Header of the emulation of the ImageManager 1024 video - * controller. - * - * Version: @(#)vid_im1024.h 1.0.0 2019/03/03 - * - * Authors: John Elliott, - * - * Copyright 2019 John Elliott. - */ -extern const device_t im1024_device; diff --git a/src/video/vid_incolor.c b/src/video/vid_incolor.c index bd0d6e36f..d2373a836 100644 --- a/src/video/vid_incolor.c +++ b/src/video/vid_incolor.c @@ -21,16 +21,15 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../lpt.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "lpt.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" -#include "vid_incolor.h" /* extended CRTC registers */ diff --git a/src/video/vid_incolor.h b/src/video/vid_incolor.h deleted file mode 100644 index d75a97186..000000000 --- a/src/video/vid_incolor.h +++ /dev/null @@ -1,4 +0,0 @@ -/* Copyright holders: John Elliott - see COPYING for more details -*/ -extern const device_t incolor_device; diff --git a/src/video/vid_mda.c b/src/video/vid_mda.c index 2651e30ea..5e8abac8d 100644 --- a/src/video/vid_mda.c +++ b/src/video/vid_mda.c @@ -21,14 +21,14 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../lpt.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "lpt.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" #include "vid_mda.h" diff --git a/src/video/vid_mga.c b/src/video/vid_mga.c new file mode 100644 index 000000000..fd27f7a54 --- /dev/null +++ b/src/video/vid_mga.c @@ -0,0 +1,4984 @@ +/* + * 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. + * + * Matrox MGA graphics card emulation. + * + * Version: @(#)vid_mga.c 1.0.3 2020/01/20 + * + * Author: Sarah Walker, + * Copyright 2008-2020 Sarah Walker. + */ +#include +#include +#include +#include +#include +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "device.h" +#include "plat.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_svga_render.h" + + +#define ROM_MYSTIQUE L"roms/video/matrox/MYSTIQUE.VBI" +#define ROM_MYSTIQUE_220 L"roms/video/matrox/Myst220_66-99mhz.vbi" + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) +#define FIFO_THRESHOLD 0xe000 + +#define WAKE_DELAY (100 * TIMER_USEC) /* 100us */ + +#define FIFO_ENTRIES (mystique->fifo_write_idx - mystique->fifo_read_idx) +#define FIFO_FULL ((mystique->fifo_write_idx - mystique->fifo_read_idx) >= (FIFO_SIZE-1)) +#define FIFO_EMPTY (mystique->fifo_read_idx == mystique->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +#define DMA_POLL_TIME_US 100 /*100us*/ +#define DMA_MAX_WORDS 256 /*256 quad words per 100us poll*/ + +/*These registers are also mirrored into 0x1dxx, with the mirrored versions starting + the blitter*/ +#define REG_DWGCTL 0x1c00 +#define REG_MACCESS 0x1c04 +#define REG_MCTLWTST 0x1c08 +#define REG_ZORG 0x1c0c +#define REG_PAT0 0x1c10 +#define REG_PAT1 0x1c14 +#define REG_PLNWT 0x1c1c +#define REG_BCOL 0x1c20 +#define REG_FCOL 0x1c24 +#define REG_SRC0 0x1c30 +#define REG_SRC1 0x1c34 +#define REG_SRC2 0x1c38 +#define REG_SRC3 0x1c3c +#define REG_XYSTRT 0x1c40 +#define REG_XYEND 0x1c44 +#define REG_SHIFT 0x1c50 +#define REG_DMAPAD 0x1c54 +#define REG_SGN 0x1c58 +#define REG_LEN 0x1c5c +#define REG_AR0 0x1c60 +#define REG_AR1 0x1c64 +#define REG_AR2 0x1c68 +#define REG_AR3 0x1c6c +#define REG_AR4 0x1c70 +#define REG_AR5 0x1c74 +#define REG_AR6 0x1c78 +#define REG_CXBNDRY 0x1c80 +#define REG_FXBNDRY 0x1c84 +#define REG_YDSTLEN 0x1c88 +#define REG_PITCH 0x1c8c +#define REG_YDST 0x1c90 +#define REG_YDSTORG 0x1c94 +#define REG_YTOP 0x1c98 +#define REG_YBOT 0x1c9c +#define REG_CXLEFT 0x1ca0 +#define REG_CXRIGHT 0x1ca4 +#define REG_FXLEFT 0x1ca8 +#define REG_FXRIGHT 0x1cac +#define REG_XDST 0x1cb0 +#define REG_DR0 0x1cc0 +#define REG_DR2 0x1cc8 +#define REG_DR3 0x1ccc +#define REG_DR4 0x1cd0 +#define REG_DR6 0x1cd8 +#define REG_DR7 0x1cdc +#define REG_DR8 0x1ce0 +#define REG_DR10 0x1ce8 +#define REG_DR11 0x1cec +#define REG_DR12 0x1cf0 +#define REG_DR14 0x1cf8 +#define REG_DR15 0x1cfc + +#define REG_FIFOSTATUS 0x1e10 +#define REG_STATUS 0x1e14 +#define REG_ICLEAR 0x1e18 +#define REG_IEN 0x1e1c +#define REG_VCOUNT 0x1e20 +#define REG_DMAMAP 0x1e30 +#define REG_RST 0x1e40 +#define REG_OPMODE 0x1e54 +#define REG_PRIMADDRESS 0x1e58 +#define REG_PRIMEND 0x1e5c +#define REG_DWG_INDIR_WT 0x1e80 + +#define REG_ATTR_IDX 0x1fc0 +#define REG_ATTR_DATA 0x1fc1 +#define REG_INSTS0 0x1fc2 +#define REG_MISC 0x1fc2 +#define REG_SEQ_IDX 0x1fc4 +#define REG_SEQ_DATA 0x1fc5 +#define REG_MISCREAD 0x1fcc +#define REG_GCTL_IDX 0x1fce +#define REG_GCTL_DATA 0x1fcf +#define REG_CRTC_IDX 0x1fd4 +#define REG_CRTC_DATA 0x1fd5 +#define REG_INSTS1 0x1fda +#define REG_CRTCEXT_IDX 0x1fde +#define REG_CRTCEXT_DATA 0x1fdf +#define REG_CACHEFLUSH 0x1fff + +#define REG_TMR0 0x2c00 +#define REG_TMR1 0x2c04 +#define REG_TMR2 0x2c08 +#define REG_TMR3 0x2c0c +#define REG_TMR4 0x2c10 +#define REG_TMR5 0x2c14 +#define REG_TMR6 0x2c18 +#define REG_TMR7 0x2c1c +#define REG_TMR8 0x2c20 +#define REG_TEXORG 0x2c24 +#define REG_TEXWIDTH 0x2c28 +#define REG_TEXHEIGHT 0x2c2c +#define REG_TEXCTL 0x2c30 +#define REG_TEXTRANS 0x2c34 +#define REG_SECADDRESS 0x2c40 +#define REG_SECEND 0x2c44 +#define REG_SOFTRAP 0x2c48 + +#define REG_PALWTADD 0x3c00 +#define REG_PALDATA 0x3c01 +#define REG_PIXRDMSK 0x3c02 +#define REG_PALRDADD 0x3c03 +#define REG_X_DATAREG 0x3c0a +#define REG_CURPOSX 0x3c0c +#define REG_CURPOSY 0x3c0e + +#define REG_STATUS_VSYNCSTS (1 << 3) + +#define CRTCX_R0_STARTADD_MASK (0xf << 0) +#define CRTCX_R0_OFFSET_MASK (3 << 4) + +#define CRTCX_R1_HTOTAL8 (1 << 0) + +#define CRTCX_R2_VTOTAL10 (1 << 0) +#define CRTCX_R2_VTOTAL11 (1 << 1) +#define CRTCX_R2_VDISPEND10 (1 << 2) +#define CRTCX_R2_VBLKSTR10 (1 << 3) +#define CRTCX_R2_VBLKSTR11 (1 << 4) +#define CRTCX_R2_VSYNCSTR10 (1 << 5) +#define CRTCX_R2_VSYNCSTR11 (1 << 6) +#define CRTCX_R2_LINECOMP10 (1 << 7) + +#define CRTCX_R3_MGAMODE (1 << 7) + +#define XREG_XCURADDL 0x04 +#define XREG_XCURADDH 0x05 +#define XREG_XCURCTRL 0x06 + +#define XREG_XCURCOL0R 0x08 +#define XREG_XCURCOL0G 0x09 +#define XREG_XCURCOL0B 0x0a + +#define XREG_XCURCOL1R 0x0c +#define XREG_XCURCOL1G 0x0d +#define XREG_XCURCOL1B 0x0e + +#define XREG_XCURCOL2R 0x10 +#define XREG_XCURCOL2G 0x11 +#define XREG_XCURCOL2B 0x12 + +#define XREG_XVREFCTRL 0x18 +#define XREG_XMULCTRL 0x19 +#define XREG_XPIXCLKCTRL 0x1a +#define XREG_XGENCTRL 0x1d +#define XREG_XMISCCTRL 0x1e + +#define XREG_XGENIOCTRL 0x2a +#define XREG_XGENIODATA 0x2b + +#define XREG_XSYSPLLM 0x2c +#define XREG_XSYSPLLN 0x2d +#define XREG_XSYSPLLP 0x2e +#define XREG_XSYSPLLSTAT 0x2f + +#define XREG_XZOOMCTRL 0x38 + +#define XREG_XPIXPLLCM 0x4c +#define XREG_XPIXPLLCN 0x4d +#define XREG_XPIXPLLCP 0x4e +#define XREG_XPIXPLLSTAT 0x4f + +#define XMISCCTRL_VGA8DAC (1 << 3) + +#define XMULCTRL_DEPTH_MASK (7 << 0) +#define XMULCTRL_DEPTH_8 (0 << 0) +#define XMULCTRL_DEPTH_15 (1 << 0) +#define XMULCTRL_DEPTH_16 (2 << 0) +#define XMULCTRL_DEPTH_24 (3 << 0) +#define XMULCTRL_DEPTH_32_OVERLAYED (4 << 0) +#define XMULCTRL_DEPTH_2G8V16 (5 << 0) +#define XMULCTRL_DEPTH_G16V16 (6 << 0) +#define XMULCTRL_DEPTH_32 (7 << 0) + +#define XSYSPLLSTAT_SYSLOCK (1 << 6) + +#define XPIXPLLSTAT_SYSLOCK (1 << 6) + +#define DWGCTRL_OPCODE_MASK (0xf << 0) +#define DWGCTRL_OPCODE_LINE_OPEN (0x0 << 0) +#define DWGCTRL_OPCODE_AUTOLINE_OPEN (0x1 << 0) +#define DWGCTRL_OPCODE_AUTOLINE_CLOSE (0x3 << 0) +#define DWGCTRL_OPCODE_TRAP (0x4 << 0) +#define DWGCTRL_OPCODE_TEXTURE_TRAP (0x6 << 0) +#define DWGCTRL_OPCODE_ILOAD_HIGH (0x7 << 0) +#define DWGCTRL_OPCODE_BITBLT (0x8 << 0) +#define DWGCTRL_OPCODE_ILOAD (0x9 << 0) +#define DWGCTRL_OPCODE_IDUMP (0xa << 0) +#define DWGCTRL_OPCODE_ILOAD_SCALE (0xd << 0) +#define DWGCTRL_OPCODE_ILOAD_HIGHV (0xe << 0) +#define DWGCTRL_OPCODE_ILOAD_FILTER (0xf << 0) /* Not implemented. */ +#define DWGCTRL_ATYPE_MASK (7 << 4) +#define DWGCTRL_ATYPE_RPL (0 << 4) +#define DWGCTRL_ATYPE_RSTR (1 << 4) +#define DWGCTRL_ATYPE_ZI (3 << 4) +#define DWGCTRL_ATYPE_BLK (4 << 4) +#define DWGCTRL_ATYPE_I (7 << 4) +#define DWGCTRL_LINEAR (1 << 7) +#define DWGCTRL_ZMODE_MASK (7 << 8) +#define DWGCTRL_ZMODE_NOZCMP (0 << 8) +#define DWGCTRL_ZMODE_ZE (2 << 8) +#define DWGCTRL_ZMODE_ZNE (3 << 8) +#define DWGCTRL_ZMODE_ZLT (4 << 8) +#define DWGCTRL_ZMODE_ZLTE (5 << 8) +#define DWGCTRL_ZMODE_ZGT (6 << 8) +#define DWGCTRL_ZMODE_ZGTE (7 << 8) +#define DWGCTRL_SOLID (1 << 11) +#define DWGCTRL_ARZERO (1 << 12) +#define DWGCTRL_SGNZERO (1 << 13) +#define DWGCTRL_SHTZERO (1 << 14) +#define DWGCTRL_BOP_MASK (0xf << 16) +#define DWGCTRL_TRANS_SHIFT (20) +#define DWGCTRL_TRANS_MASK (0xf << DWGCTRL_TRANS_SHIFT) +#define DWGCTRL_BLTMOD_MASK (0xf << 25) +#define DWGCTRL_BLTMOD_BMONOLEF (0x0 << 25) +#define DWGCTRL_BLTMOD_BFCOL (0x2 << 25) +#define DWGCTRL_BLTMOD_BU32BGR (0x3 << 25) +#define DWGCTRL_BLTMOD_BMONOWF (0x4 << 25) +#define DWGCTRL_BLTMOD_BU32RGB (0x7 << 25) +#define DWGCTRL_BLTMOD_BUYUV (0xe << 25) +#define DWGCTRL_BLTMOD_BU24RGB (0xf << 25) +#define DWGCTRL_PATTERN (1 << 29) +#define DWGCTRL_TRANSC (1 << 30) +#define BOP(x) ((x) << 16) + +#define MACCESS_PWIDTH_MASK (3 << 0) +#define MACCESS_PWIDTH_8 (0 << 0) +#define MACCESS_PWIDTH_16 (1 << 0) +#define MACCESS_PWIDTH_32 (2 << 0) +#define MACCESS_PWIDTH_24 (3 << 0) +#define MACCESS_TLUTLOAD (1 << 29) +#define MACCESS_NODITHER (1 << 30) +#define MACCESS_DIT555 (1 << 31) + +#define PITCH_MASK 0x7e0 +#define PITCH_YLIN (1 << 15) + +#define SGN_SDYDXL (1 << 0) +#define SGN_SCANLEFT (1 << 0) +#define SGN_SDXL (1 << 1) +#define SGN_SDY (1 << 2) +#define SGN_SDXR (1 << 5) + +#define DMA_ADDR_MASK 0xfffffffc +#define DMA_MODE_MASK 3 + +#define DMA_MODE_REG 0 +#define DMA_MODE_BLIT 1 +#define DMA_MODE_VECTOR 2 + +#define STATUS_SOFTRAPEN (1 << 0) +#define STATUS_VLINEPEN (1 << 5) +#define STATUS_DWGENGSTS (1 << 16) +#define STATUS_ENDPRDMASTS (1 << 17) + +#define ICLEAR_SOFTRAPICLR (1 << 0) +#define ICLEAR_VLINEICLR (1 << 5) + +#define IEN_SOFTRAPEN (1 << 0) + +#define TEXCTL_TEXFORMAT_MASK (7 << 0) +#define TEXCTL_TEXFORMAT_TW4 (0 << 0) +#define TEXCTL_TEXFORMAT_TW8 (1 << 0) +#define TEXCTL_TEXFORMAT_TW15 (2 << 0) +#define TEXCTL_TEXFORMAT_TW16 (3 << 0) +#define TEXCTL_TEXFORMAT_TW12 (4 << 0) +#define TEXCTL_PALSEL_MASK (0xf << 4) +#define TEXCTL_TPITCH_SHIFT (16) +#define TEXCTL_TPITCH_MASK (7 << TEXCTL_TPITCH_SHIFT) +#define TEXCTL_NPCEN (1 << 21) +#define TEXCTL_DECALCKEY (1 << 24) +#define TEXCTL_TAKEY (1 << 25) +#define TEXCTL_TAMASK (1 << 26) +#define TEXCTL_CLAMPV (1 << 27) +#define TEXCTL_CLAMPU (1 << 28) +#define TEXCTL_TMODULATE (1 << 29) +#define TEXCTL_STRANS (1 << 30) +#define TEXCTL_ITRANS (1 << 31) + +#define TEXHEIGHT_TH_MASK (0x3f << 0) +#define TEXHEIGHT_THMASK_SHIFT (18) +#define TEXHEIGHT_THMASK_MASK (0x7ff << TEXHEIGHT_THMASK_SHIFT) + +#define TEXWIDTH_TW_MASK (0x3f << 0) +#define TEXWIDTH_TWMASK_SHIFT (18) +#define TEXWIDTH_TWMASK_MASK (0x7ff << TEXWIDTH_TWMASK_SHIFT) + +#define TEXTRANS_TCKEY_MASK (0xffff) +#define TEXTRANS_TKMASK_SHIFT (16) +#define TEXTRANS_TKMASK_MASK (0xffff << TEXTRANS_TKMASK_SHIFT) + +#define DITHER_565 0 +#define DITHER_NONE_565 1 +#define DITHER_555 2 +#define DITHER_NONE_555 3 + + +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITE_CTRL_BYTE = (0x01 << 24), + FIFO_WRITE_CTRL_LONG = (0x02 << 24), + FIFO_WRITE_ILOAD_LONG = (0x03 << 24) +}; + +enum +{ + DMA_STATE_IDLE = 0, + DMA_STATE_PRI, + DMA_STATE_SEC +}; + + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct mystique_t +{ + svga_t svga; + + rom_t bios_rom; + + mem_mapping_t lfb_mapping, ctrl_mapping, + iload_mapping; + + uint8_t int_line, xcurctrl, + xsyspllm, xsysplln, xsyspllp, + xgenioctrl, xgeniodata, + xmulctrl, xgenctrl, + xmiscctrl, xpixclkctrl, + xvrefctrl, ien, dmamod, + dmadatasiz, dirdatasiz; + + uint8_t pci_regs[256], crtcext_regs[6], + xreg_regs[256], dmamap[16]; + + int card, vram_size, crtcext_idx, xreg_idx, + xzoomctrl, + pixel_count, trap_count; + + volatile int busy, blitter_submit_refcount, + blitter_submit_dma_refcount, blitter_complete_refcount, + endprdmasts_pending, softrap_pending, + fifo_read_idx, fifo_write_idx; + + uint32_t vram_mask, vram_mask_w, vram_mask_l, + lfb_base, ctrl_base, iload_base, + ma_latch_old, maccess, mctlwtst, maccess_running, + status, softrap_pending_val; + + uint64_t blitter_time, status_time; + + pc_timer_t softrap_pending_timer, wake_timer; + + fifo_entry_t fifo[FIFO_SIZE]; + + thread_t *fifo_thread; + + event_t *wake_fifo_thread, *fifo_not_full_event; + + struct + { + int m, n, p, s; + } xpixpll[3]; + + struct + { + uint8_t funcnt, stylelen, + dmamod; + + int16_t fxleft, fxright, + xdst; + + uint16_t cxleft, cxright, + length; + + int xoff, yoff, selline, ydst, + length_cur, iload_rem_count, idump_end_of_line, words, + ta_key, ta_mask, lastpix_r, lastpix_g, + lastpix_b, highv_line, beta, dither; + + int pattern[8][8]; + + uint32_t dwgctrl, dwgctrl_running, bcol, fcol, + pitch, plnwt, ybot, ydstorg, + ytop, texorg, texwidth, texheight, + texctl, textrans, zorg, ydst_lin, + src_addr, z_base, iload_rem_data, highv_data; + + uint32_t src[4], ar[7], + dr[16], tmr[9]; + + struct + { + int sdydxl, scanleft, sdxl, sdy, + sdxr; + } sgn; + } dwgreg; + + struct + { + uint8_t r, g, b; + } lut[256]; + + struct + { + uint16_t pos_x, pos_y, + addr; + uint32_t col[3]; + } cursor; + + struct + { + int pri_pos, sec_pos, iload_pos, + pri_state, sec_state, iload_state, state; + + uint32_t primaddress, primend, secaddress, secend, + pri_header, sec_header, + iload_header; + + mutex_t *lock; + } dma; +} mystique_t; + + +static const uint8_t trans_masks[16][16] = +{ + { + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }, + { + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1 + }, + { + 0, 1, 0, 1, + 1, 0, 1, 0, + 0, 1, 0, 1, + 1, 0, 1, 0 + }, + { + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 1, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 1 + }, + { + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1 + }, + { + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 1, 0 + }, + { + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 1, + 0, 0, 0, 0, + 0, 1, 0, 0 + }, + { + 0, 0, 1, 0, + 0, 0, 0, 0, + 1, 0, 0, 0, + 0, 0, 0, 0 + }, + { + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 + } +}; + + +static int8_t dither5[256][2][2]; +static int8_t dither6[256][2][2]; + +static video_timings_t timing_matrox_mystique = {VIDEO_BUS, 4, 4, 4, 10, 10, 10}; + + +static void mystique_start_blit(mystique_t *mystique); +static void mystique_update_irqs(mystique_t *mystique); + +static void wake_fifo_thread(mystique_t *mystique); +static void wait_fifo_idle(mystique_t *mystique); +static void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type); + +static uint8_t mystique_readb_linear(uint32_t addr, void *p); +static uint16_t mystique_readw_linear(uint32_t addr, void *p); +static uint32_t mystique_readl_linear(uint32_t addr, void *p); +static void mystique_writeb_linear(uint32_t addr, uint8_t val, void *p); +static void mystique_writew_linear(uint32_t addr, uint16_t val, void *p); +static void mystique_writel_linear(uint32_t addr, uint32_t val, void *p); + +static void mystique_recalc_mapping(mystique_t *mystique); +static int mystique_line_compare(svga_t *svga); + +static uint8_t mystique_iload_read_b(uint32_t addr, void *p); +static uint32_t mystique_iload_read_l(uint32_t addr, void *p); +static void mystique_iload_write_b(uint32_t addr, uint8_t val, void *p); +static void mystique_iload_write_l(uint32_t addr, uint32_t val, void *p); + +static uint32_t blit_idump_read(mystique_t *mystique); +static void blit_iload_write(mystique_t *mystique, uint32_t data, int size); + + +void +mystique_out(uint16_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t old; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3c8: + mystique->xreg_idx = val; + break; + + case 0x3cf: + if ((svga->gdcaddr & 15) == 6 && svga->gdcreg[6] != val) { + svga->gdcreg[svga->gdcaddr & 15] = val; + mystique_recalc_mapping(mystique); + return; + } + break; + + case 0x3D4: + svga->crtcreg = val & 0x3f; + return; + case 0x3D5: + if (((svga->crtcreg & 31) < 7) && (svga->crtc[0x11] & 0x80)) + return; + if (((svga->crtcreg & 31) == 7) && (svga->crtc[0x11] & 0x80)) + val = (svga->crtc[7] & ~0x10) | (val & 0x10); + old = svga->crtc[svga->crtcreg & 0x3f]; + svga->crtc[svga->crtcreg & 31] = val; + if (old != val) { + if ((svga->crtcreg & 31) < 0xE || (svga->crtcreg & 31) > 0x10) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + } + break; + + case 0x3de: + mystique->crtcext_idx = val; + break; + case 0x3df: + if (mystique->crtcext_idx < 6) + mystique->crtcext_regs[mystique->crtcext_idx] = val; + if (mystique->crtcext_idx < 4) { + svga->fullchange = changeframecount; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 3) { + if (val & CRTCX_R3_MGAMODE) + svga->fb_only = 1; + else + svga->fb_only = 0; + svga_recalctimings(svga); + } + if (mystique->crtcext_idx == 4) { + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (val & 0x7f) << 16; + svga->write_bank = (val & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (val & 0x7e) << 16; + svga->write_bank = (val & 0x7e) << 16; + } + } + break; + } + + svga_out(addr, val, svga); +} + + +uint8_t +mystique_in(uint16_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t temp = 0xff; + + if ((((addr&0xFFF0) == 0x3D0 || (addr&0xFFF0) == 0x3B0) && addr < 0x3de) && !(svga->miscout & 1)) + addr ^= 0x60; + + switch (addr) { + case 0x3D4: + temp = svga->crtcreg; + break; + case 0x3D5: + temp = svga->crtc[svga->crtcreg & 0x3f]; + break; + + case 0x3df: + if (mystique->crtcext_idx < 6) + temp = mystique->crtcext_regs[mystique->crtcext_idx]; + break; + + default: + temp = svga_in(addr, svga); + break; + } + + return temp; +} + + +static int +mystique_line_compare(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + + mystique->status |= STATUS_VLINEPEN; + mystique_update_irqs(mystique); + + return 0; +} + + +void +mystique_recalctimings(svga_t *svga) +{ + mystique_t *mystique = (mystique_t *)svga->p; + int clk_sel = (svga->miscout >> 2) & 3; + + if (clk_sel & 2) { + int m = mystique->xpixpll[2].m; + int n = mystique->xpixpll[2].n; + int p = mystique->xpixpll[2].p; + + double fvco = 14318181.0 * (n + 1) / (m + 1); + double fo = fvco / (p + 1); + + svga->clock = (cpuclock * (float)(1ull << 32)) / fo; + } + + if (mystique->crtcext_regs[1] & CRTCX_R1_HTOTAL8) + svga->htotal += 0x100; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL10) + svga->vtotal += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VTOTAL11) + svga->vtotal += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VDISPEND10) + svga->dispend += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR10) + svga->vblankstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VBLKSTR11) + svga->vblankstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR10) + svga->vsyncstart += 0x400; + if (mystique->crtcext_regs[2] & CRTCX_R2_VSYNCSTR11) + svga->vsyncstart += 0x800; + if (mystique->crtcext_regs[2] & CRTCX_R2_LINECOMP10) + svga->split += 0x400; + + svga->interlace = !!(mystique->crtcext_regs[0] & 0x80); + + if (mystique->crtcext_regs[3] & CRTCX_R3_MGAMODE) { + int row_offset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4); + + svga->lowres = 0; + svga->char_width = 8; + svga->hdisp = (svga->crtc[1] + 1) * 8; + svga->hdisp_time = svga->hdisp; + if (svga->interlace) + svga->rowoffset = row_offset; + else + svga->rowoffset = row_offset * 2; + svga->ma_latch = ((mystique->crtcext_regs[0] & CRTCX_R0_STARTADD_MASK) << 17) | + (svga->crtc[0xc] << 9) | (svga->crtc[0xd] << 1); + + /*Mystique, unlike most SVGA cards, allows display start to take + effect mid-screen*/ + if (svga->ma_latch != mystique->ma_latch_old) { + if (svga->interlace && svga->oddeven) + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2) + (svga->rowoffset << 1); + else + svga->ma = svga->maback = (svga->maback - (mystique->ma_latch_old << 2)) + (svga->ma_latch << 2); + mystique->ma_latch_old = svga->ma_latch; + } + + switch (mystique->xmulctrl & XMULCTRL_DEPTH_MASK) { + case XMULCTRL_DEPTH_8: + case XMULCTRL_DEPTH_2G8V16: + svga->render = svga_render_8bpp_highres; + svga->bpp = 8; + break; + case XMULCTRL_DEPTH_15: + case XMULCTRL_DEPTH_G16V16: + svga->render = svga_render_15bpp_highres; + svga->bpp = 15; + break; + case XMULCTRL_DEPTH_16: + svga->render = svga_render_16bpp_highres; + svga->bpp = 16; + break; + case XMULCTRL_DEPTH_24: + svga->render = svga_render_24bpp_highres; + svga->bpp = 24; + break; + case XMULCTRL_DEPTH_32: + case XMULCTRL_DEPTH_32_OVERLAYED: + svga->render = svga_render_32bpp_highres; + svga->bpp = 32; + break; + } + + svga->line_compare = mystique_line_compare; + + mem_mapping_set_handler(&mystique->lfb_mapping, + mystique_readb_linear, mystique_readw_linear, mystique_readl_linear, + mystique_writeb_linear, mystique_writew_linear, mystique_writel_linear); + } else { + svga->line_compare = NULL; + svga->bpp = 8; + + mem_mapping_set_handler(&mystique->lfb_mapping, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear); + } +} + + +static +void mystique_recalc_mapping(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + + io_removehandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + if ((mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO) && (mystique->pci_regs[0x41] & 1)) + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + + if (!(mystique->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) { + mem_mapping_disable(&svga->mapping); + mem_mapping_disable(&mystique->ctrl_mapping); + mem_mapping_disable(&mystique->lfb_mapping); + mem_mapping_disable(&mystique->iload_mapping); + return; + } + + if (mystique->ctrl_base) + mem_mapping_set_addr(&mystique->ctrl_mapping, mystique->ctrl_base, 0x4000); + else + mem_mapping_disable(&mystique->ctrl_mapping); + + if (mystique->lfb_base) + mem_mapping_set_addr(&mystique->lfb_mapping, mystique->lfb_base, 0x800000); + else + mem_mapping_disable(&mystique->lfb_mapping); + + if (mystique->iload_base) + mem_mapping_set_addr(&mystique->iload_mapping, mystique->iload_base, 0x800000); + else + mem_mapping_disable(&mystique->iload_mapping); + + if (mystique->pci_regs[0x41] & 1) { + switch (svga->gdcreg[6] & 0x0C) { + case 0x0: /*128k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0x1ffff; + break; + case 0x4: /*64k at A0000*/ + mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); + svga->banked_mask = 0xffff; + break; + case 0x8: /*32k at B0000*/ + mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); + svga->banked_mask = 0x7fff; + break; + case 0xC: /*32k at B8000*/ + mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); + svga->banked_mask = 0x7fff; + break; + } + if (svga->gdcreg[6] & 0xc) { + /*64k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7f) << 16; + } else { + /*128k banks*/ + svga->read_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + svga->write_bank = (mystique->crtcext_regs[4] & 0x7e) << 16; + } + } else + mem_mapping_disable(&svga->mapping); +} + + +static void +mystique_update_irqs(mystique_t *mystique) +{ + int irq = 0; + + if ((mystique->status & mystique->ien) & STATUS_SOFTRAPEN) + irq = 1; + + if (irq) + pci_set_irq(mystique->card, PCI_INTA); + else + pci_clear_irq(mystique->card, PCI_INTA); +} + + +#define READ8(addr, var) switch ((addr) & 3) { \ + case 0: ret = (var) & 0xff; break; \ + case 1: ret = ((var) >> 8) & 0xff; break; \ + case 2: ret = ((var) >> 16) & 0xff; break; \ + case 3: ret = ((var) >> 24) & 0xff; break; \ + } + +#define WRITE8(addr, var, val) switch ((addr) & 3) { \ + case 0: var = (var & 0xffffff00) | (val); break; \ + case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \ + case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \ + case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \ + } + + +static uint8_t +mystique_read_xreg(mystique_t *mystique, int reg) +{ + uint8_t ret = 0xff; + + switch (reg) { + case XREG_XCURADDL: + ret = mystique->cursor.addr & 0xff; + break; + case XREG_XCURADDH: + ret = mystique->cursor.addr >> 8; + break; + case XREG_XCURCTRL: + ret = mystique->xcurctrl; + break; + + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + READ8(reg, mystique->cursor.col[0]); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + READ8(reg, mystique->cursor.col[1]); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + READ8(reg, mystique->cursor.col[2]); + break; + + case XREG_XMULCTRL: + ret = mystique->xmulctrl; + break; + + case XREG_XMISCCTRL: + ret = mystique->xmiscctrl; + break; + + case XREG_XGENCTRL: + ret = mystique->xgenctrl; + break; + + case XREG_XGENIOCTRL: + ret = mystique->xgenioctrl; + break; + case XREG_XGENIODATA: + ret = mystique->xgeniodata; + break; + + case XREG_XSYSPLLM: + ret = mystique->xsyspllm; + break; + case XREG_XSYSPLLN: + ret = mystique->xsysplln; + break; + case XREG_XSYSPLLP: + ret = mystique->xsyspllp; + break; + + case XREG_XZOOMCTRL: + ret = mystique->xzoomctrl; + break; + + case XREG_XPIXCLKCTRL: + ret = mystique->xpixclkctrl; + break; + + case XREG_XSYSPLLSTAT: + ret = XSYSPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLSTAT: + ret = XPIXPLLSTAT_SYSLOCK; + break; + + case XREG_XPIXPLLCM: + ret = mystique->xpixpll[2].m; + break; + case XREG_XPIXPLLCN: + ret = mystique->xpixpll[2].n; + break; + case XREG_XPIXPLLCP: + ret = mystique->xpixpll[2].p | (mystique->xpixpll[2].s << 3); + break; + + case 0x00: case 0x20: case 0x3f: + ret = 0xff; + break; + + default: + if (reg >= 0x50) + ret = 0xff; + break; + } + + return ret; +} + + +static void +mystique_write_xreg(mystique_t *mystique, int reg, uint8_t val) +{ + svga_t *svga = &mystique->svga; + + switch (reg) { + case XREG_XCURADDL: + mystique->cursor.addr = (mystique->cursor.addr & 0x1f00) | val; + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + case XREG_XCURADDH: + mystique->cursor.addr = (mystique->cursor.addr & 0x00ff) | ((val & 0x1f) << 8); + svga->hwcursor.addr = mystique->cursor.addr << 10; + break; + + case XREG_XCURCTRL: + mystique->xcurctrl = val; + svga->hwcursor.ena = (val & 3) ? 1 : 0; + break; + + case XREG_XCURCOL0R: case XREG_XCURCOL0G: case XREG_XCURCOL0B: + WRITE8(reg, mystique->cursor.col[0], val); + break; + case XREG_XCURCOL1R: case XREG_XCURCOL1G: case XREG_XCURCOL1B: + WRITE8(reg, mystique->cursor.col[1], val); + break; + case XREG_XCURCOL2R: case XREG_XCURCOL2G: case XREG_XCURCOL2B: + WRITE8(reg, mystique->cursor.col[2], val); + break; + + case XREG_XMULCTRL: + mystique->xmulctrl = val; + break; + + case XREG_XMISCCTRL: + mystique->xmiscctrl = val; + svga_set_ramdac_type(svga, (val & XMISCCTRL_VGA8DAC) ? RAMDAC_8BIT : RAMDAC_6BIT); + break; + + case XREG_XGENCTRL: + mystique->xgenctrl = val; + break; + + case XREG_XVREFCTRL: + mystique->xvrefctrl = val; + break; + + case XREG_XGENIOCTRL: + mystique->xgenioctrl = val; + break; + case XREG_XGENIODATA: + mystique->xgeniodata = val; + break; + + case XREG_XSYSPLLM: + mystique->xsyspllm = val; + break; + case XREG_XSYSPLLN: + mystique->xsysplln = val; + break; + case XREG_XSYSPLLP: + mystique->xsyspllp = val; + break; + + case XREG_XZOOMCTRL: + mystique->xzoomctrl = val & 3; + break; + + case XREG_XPIXCLKCTRL: + mystique->xpixclkctrl = val; + break; + + case XREG_XPIXPLLCM: + mystique->xpixpll[2].m = val; + break; + case XREG_XPIXPLLCN: + mystique->xpixpll[2].n = val; + break; + case XREG_XPIXPLLCP: + mystique->xpixpll[2].p = val & 7; + mystique->xpixpll[2].s = (val >> 3) & 3; + break; + + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x07: case 0x0b: case 0x0f: + case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x1b: case 0x1c: case 0x20: case 0x39: case 0x3b: case 0x3f: + case 0x47: case 0x4b: + break; + + default: + break; + } +} + + +static uint8_t +mystique_ctrl_read_b(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + uint8_t ret = 0xff; + int fifocount; + + switch (addr & 0x3fff) { + case REG_FIFOSTATUS: + fifocount = FIFO_SIZE - FIFO_ENTRIES; + if (fifocount > 64) + fifocount = 64; + ret = fifocount; + break; + case REG_FIFOSTATUS+1: + if (FIFO_EMPTY) + ret |= 2; + else if (FIFO_ENTRIES >= 64) + ret |= 1; + break; + case REG_FIFOSTATUS+2: case REG_FIFOSTATUS+3: + ret = 0; + break; + + case REG_STATUS: + ret = mystique->status & 0xff; + if (svga->cgastat & 8) + ret |= REG_STATUS_VSYNCSTS; + break; + case REG_STATUS+1: + ret = (mystique->status >> 8) & 0xff; + break; + case REG_STATUS+2: + ret = (mystique->status >> 16) & 0xff; + if (mystique->busy || + ((mystique->blitter_submit_refcount + mystique->blitter_submit_dma_refcount) != mystique->blitter_complete_refcount) || + !FIFO_EMPTY) + ret |= (STATUS_DWGENGSTS >> 16); + break; + case REG_STATUS+3: + ret = (mystique->status >> 24) & 0xff; + break; + + case REG_IEN: + ret = mystique->ien & 0x64; + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + ret = 0; + break; + + case REG_OPMODE: + ret = mystique->dmamod << 2; + break; + case REG_OPMODE+1: + ret = mystique->dmadatasiz; + break; + case REG_OPMODE+2: + ret = mystique->dirdatasiz; + break; + case REG_OPMODE+3: + break; + + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + READ8(addr, mystique->dma.primaddress); + break; + case REG_PRIMEND: case REG_PRIMEND+1: case REG_PRIMEND+2: case REG_PRIMEND+3: + READ8(addr, mystique->dma.primend); + break; + + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + READ8(addr, mystique->dma.secaddress); + break; + + case REG_VCOUNT: case REG_VCOUNT+1: case REG_VCOUNT+2: case REG_VCOUNT+3: + READ8(addr, svga->vc); + break; + + case REG_ATTR_IDX: + ret = svga_in(0x3c0, svga); + break; + case REG_ATTR_DATA: + ret = svga_in(0x3c1, svga); + break; + + case REG_INSTS0: + ret = svga_in(0x3c2, svga); + break; + + case REG_SEQ_IDX: + ret = svga_in(0x3c4, svga); + break; + case REG_SEQ_DATA: + ret = svga_in(0x3c5, svga); + break; + + case REG_MISCREAD: + ret = svga_in(0x3cc, svga); + break; + + case REG_GCTL_IDX: + ret = mystique_in(0x3ce, mystique); + break; + case REG_GCTL_DATA: + ret = mystique_in(0x3cf, mystique); + break; + + case REG_CRTC_IDX: + ret = mystique_in(0x3d4, mystique); + break; + case REG_CRTC_DATA: + ret = mystique_in(0x3d5, mystique); + break; + + case REG_INSTS1: + ret = mystique_in(0x3da, mystique); + break; + + case REG_CRTCEXT_IDX: + ret = mystique_in(0x3de, mystique); + break; + case REG_CRTCEXT_DATA: + ret = mystique_in(0x3df, mystique); + break; + + case REG_PALWTADD: + ret = svga_in(0x3c8, svga); + break; + case REG_PALDATA: + ret = svga_in(0x3c9, svga); + break; + case REG_PIXRDMSK: + ret = svga_in(0x3c6, svga); + break; + case REG_PALRDADD: + ret = svga_in(0x3c7, svga); + break; + + case REG_X_DATAREG: + ret = mystique_read_xreg(mystique, mystique->xreg_idx); + break; + + case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: + case REG_ICLEAR: case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + case 0x2c30: case 0x2c31: case 0x2c32: case 0x2c33: + case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c00 && (addr & 0x3fff) < 0x2c40) + break; + if ((addr & 0x3fff) >= 0x3e00) + break; + break; + } + + return ret; +} + + +static void +mystique_accel_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + int x; + + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3fff) { + case REG_MACCESS: case REG_MACCESS+1: case REG_MACCESS+2: case REG_MACCESS+3: + WRITE8(addr, mystique->maccess, val); + mystique->dwgreg.dither = mystique->maccess >> 30; + break; + + case REG_MCTLWTST: case REG_MCTLWTST+1: case REG_MCTLWTST+2: case REG_MCTLWTST+3: + WRITE8(addr, mystique->mctlwtst, val); + break; + + case REG_PAT0: case REG_PAT0+1: case REG_PAT0+2: case REG_PAT0+3: + case REG_PAT1: case REG_PAT1+1: case REG_PAT1+2: case REG_PAT1+3: + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[addr & 7][x] = val & (1 << (7-x)); + break; + + case REG_XYSTRT: case REG_XYSTRT+1: + WRITE8(addr&1, mystique->dwgreg.ar[5], val); + if (mystique->dwgreg.ar[5] & 0x8000) + mystique->dwgreg.ar[5] |= 0xffff8000; + else + mystique->dwgreg.ar[5] &= ~0xffff8000; + WRITE8(addr&1, mystique->dwgreg.xdst, val); + break; + case REG_XYSTRT+2: case REG_XYSTRT+3: + WRITE8(addr & 1, mystique->dwgreg.ar[6], val); + if (mystique->dwgreg.ar[6] & 0x8000) + mystique->dwgreg.ar[6] |= 0xffff8000; + else + mystique->dwgreg.ar[6] &= ~0xffff8000; + WRITE8(addr & 1, mystique->dwgreg.ydst, val); + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_XYEND: case REG_XYEND+1: + WRITE8(addr&1, mystique->dwgreg.ar[0], val); + if (mystique->dwgreg.ar[0] & 0x8000) + mystique->dwgreg.ar[0] |= 0xffff8000; + else + mystique->dwgreg.ar[0] &= ~0xffff8000; + break; + case REG_XYEND+2: case REG_XYEND+3: + WRITE8(addr & 1, mystique->dwgreg.ar[2], val); + if (mystique->dwgreg.ar[2] & 0x8000) + mystique->dwgreg.ar[2] |= 0xffff8000; + else + mystique->dwgreg.ar[2] &= ~0xffff8000; + break; + + case REG_SGN: + mystique->dwgreg.sgn.sdydxl = val & SGN_SDYDXL; + mystique->dwgreg.sgn.scanleft = val & SGN_SCANLEFT; + mystique->dwgreg.sgn.sdxl = val & SGN_SDXL; + mystique->dwgreg.sgn.sdy = val & SGN_SDY; + mystique->dwgreg.sgn.sdxr = val & SGN_SDXR; + break; + case REG_SGN+1: case REG_SGN+2: case REG_SGN+3: + break; + + case REG_LEN: case REG_LEN+1: + WRITE8(addr, mystique->dwgreg.length, val); + break; + case REG_LEN+2: + break; + case REG_LEN+3: + mystique->dwgreg.beta = val >> 4; + if (!mystique->dwgreg.beta) + mystique->dwgreg.beta = 16; + break; + + case REG_CXBNDRY: case REG_CXBNDRY+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXBNDRY+2: case REG_CXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.cxright, val); + break; + case REG_FXBNDRY: case REG_FXBNDRY+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXBNDRY+2: case REG_FXBNDRY+3: + WRITE8(addr & 1, mystique->dwgreg.fxright, val); + break; + + case REG_YDSTLEN: case REG_YDSTLEN+1: + WRITE8(addr, mystique->dwgreg.length, val); + /* pclog("Write YDSTLEN+%i %i\n", addr&1, mystique->dwgreg.length); */ + break; + case REG_YDSTLEN+2: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & ~0xff) | val; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_YDSTLEN+3: + mystique->dwgreg.ydst = (mystique->dwgreg.ydst & 0xff) | (((int32_t)(int8_t)val) << 8); + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_XDST: case REG_XDST+1: + WRITE8(addr & 1, mystique->dwgreg.xdst, val); + break; + case REG_XDST+2: case REG_XDST+3: + break; + + case REG_YDSTORG: case REG_YDSTORG+1: case REG_YDSTORG+2: case REG_YDSTORG+3: + WRITE8(addr, mystique->dwgreg.ydstorg, val); + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; + break; + case REG_YTOP: case REG_YTOP+1: case REG_YTOP+2: case REG_YTOP+3: + WRITE8(addr, mystique->dwgreg.ytop, val); + break; + case REG_YBOT: case REG_YBOT+1: case REG_YBOT+2: case REG_YBOT+3: + WRITE8(addr, mystique->dwgreg.ybot, val); + break; + + case REG_CXLEFT: case REG_CXLEFT+1: + WRITE8(addr, mystique->dwgreg.cxleft, val); + break; + case REG_CXLEFT+2: case REG_CXLEFT+3: + break; + case REG_CXRIGHT: case REG_CXRIGHT+1: + WRITE8(addr, mystique->dwgreg.cxright, val); + break; + case REG_CXRIGHT+2: case REG_CXRIGHT+3: + break; + + case REG_FXLEFT: case REG_FXLEFT+1: + WRITE8(addr, mystique->dwgreg.fxleft, val); + break; + case REG_FXLEFT+2: case REG_FXLEFT+3: + break; + case REG_FXRIGHT: case REG_FXRIGHT+1: + WRITE8(addr, mystique->dwgreg.fxright, val); + break; + case REG_FXRIGHT+2: case REG_FXRIGHT+3: + break; + + case REG_SECADDRESS: case REG_SECADDRESS+1: case REG_SECADDRESS+2: case REG_SECADDRESS+3: + WRITE8(addr, mystique->dma.secaddress, val); + mystique->dma.sec_state = 0; + break; + + case REG_TMR0: case REG_TMR0+1: case REG_TMR0+2: case REG_TMR0+3: + WRITE8(addr, mystique->dwgreg.tmr[0], val); + break; + case REG_TMR1: case REG_TMR1+1: case REG_TMR1+2: case REG_TMR1+3: + WRITE8(addr, mystique->dwgreg.tmr[1], val); + break; + case REG_TMR2: case REG_TMR2+1: case REG_TMR2+2: case REG_TMR2+3: + WRITE8(addr, mystique->dwgreg.tmr[2], val); + break; + case REG_TMR3: case REG_TMR3+1: case REG_TMR3+2: case REG_TMR3+3: + WRITE8(addr, mystique->dwgreg.tmr[3], val); + break; + case REG_TMR4: case REG_TMR4+1: case REG_TMR4+2: case REG_TMR4+3: + WRITE8(addr, mystique->dwgreg.tmr[4], val); + break; + case REG_TMR5: case REG_TMR5+1: case REG_TMR5+2: case REG_TMR5+3: + WRITE8(addr, mystique->dwgreg.tmr[5], val); + break; + case REG_TMR6: case REG_TMR6+1: case REG_TMR6+2: case REG_TMR6+3: + WRITE8(addr, mystique->dwgreg.tmr[6], val); + break; + case REG_TMR7: case REG_TMR7+1: case REG_TMR7+2: case REG_TMR7+3: + WRITE8(addr, mystique->dwgreg.tmr[7], val); + break; + case REG_TMR8: case REG_TMR8+1: case REG_TMR8+2: case REG_TMR8+3: + WRITE8(addr, mystique->dwgreg.tmr[8], val); + break; + + case REG_TEXORG: case REG_TEXORG+1: case REG_TEXORG+2: case REG_TEXORG+3: + WRITE8(addr, mystique->dwgreg.texorg, val); + break; + case REG_TEXWIDTH: case REG_TEXWIDTH+1: case REG_TEXWIDTH+2: case REG_TEXWIDTH+3: + WRITE8(addr, mystique->dwgreg.texwidth, val); + break; + case REG_TEXHEIGHT: case REG_TEXHEIGHT+1: case REG_TEXHEIGHT+2: case REG_TEXHEIGHT+3: + WRITE8(addr, mystique->dwgreg.texheight, val); + break; + case REG_TEXCTL: case REG_TEXCTL+1: case REG_TEXCTL+2: case REG_TEXCTL+3: + WRITE8(addr, mystique->dwgreg.texctl, val); + mystique->dwgreg.ta_key = (mystique->dwgreg.texctl & TEXCTL_TAKEY) ? 1 : 0; + mystique->dwgreg.ta_mask = (mystique->dwgreg.texctl & TEXCTL_TAMASK) ? 1 : 0; + break; + case REG_TEXTRANS: case REG_TEXTRANS+1: case REG_TEXTRANS+2: case REG_TEXTRANS+3: + WRITE8(addr, mystique->dwgreg.textrans, val); + break; + + case 0x1c28: case 0x1c29: case 0x1c2a: case 0x1c2b: + case 0x1c2c: case 0x1c2d: case 0x1c2e: case 0x1c2f: + case 0x1cc4: case 0x1cc5: case 0x1cc6: case 0x1cc7: + case 0x1cd4: case 0x1cd5: case 0x1cd6: case 0x1cd7: + case 0x1ce4: case 0x1ce5: case 0x1ce6: case 0x1ce7: + case 0x1cf4: case 0x1cf5: case 0x1cf6: case 0x1cf7: + break; + + case REG_OPMODE: + mystique->dwgreg.dmamod = (val >> 2) & 3; + mystique->dma.iload_state = 0; + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + + +static void +mystique_ctrl_write_b(uint32_t addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + svga_t *svga = &mystique->svga; + + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_b(addr, val, p); + return; + } + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + return; + } + + switch (addr & 0x3fff) { + case REG_ICLEAR: + if (val & ICLEAR_SOFTRAPICLR) { + mystique->status &= ~STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } + if (val & ICLEAR_VLINEICLR) { + mystique->status &= ~STATUS_VLINEPEN; + mystique_update_irqs(mystique); + } + break; + case REG_ICLEAR+1: case REG_ICLEAR+2: case REG_ICLEAR+3: + break; + + case REG_IEN: + mystique->ien = val & 0x65; + break; + case REG_IEN+1: case REG_IEN+2: case REG_IEN+3: + break; + + case REG_OPMODE: + thread_wait_mutex(mystique->dma.lock); + mystique->dma.state = DMA_STATE_IDLE; /* Interrupt DMA. */ + thread_release_mutex(mystique->dma.lock); + mystique->dmamod = (val >> 2) & 3; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_BYTE); + break; + case REG_OPMODE+1: + mystique->dmadatasiz = val & 3; + break; + case REG_OPMODE+2: + mystique->dirdatasiz = val & 3; + break; + case REG_OPMODE+3: + break; + + case REG_PRIMADDRESS: case REG_PRIMADDRESS+1: case REG_PRIMADDRESS+2: case REG_PRIMADDRESS+3: + thread_wait_mutex(mystique->dma.lock); + WRITE8(addr, mystique->dma.primaddress, val); + mystique->dma.pri_state = 0; + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DMAMAP: case REG_DMAMAP+0x1: case REG_DMAMAP+0x2: case REG_DMAMAP+0x3: + case REG_DMAMAP+0x4: case REG_DMAMAP+0x5: case REG_DMAMAP+0x6: case REG_DMAMAP+0x7: + case REG_DMAMAP+0x8: case REG_DMAMAP+0x9: case REG_DMAMAP+0xa: case REG_DMAMAP+0xb: + case REG_DMAMAP+0xc: case REG_DMAMAP+0xd: case REG_DMAMAP+0xe: case REG_DMAMAP+0xf: + mystique->dmamap[addr & 0xf] = val; + break; + + case REG_RST: case REG_RST+1: case REG_RST+2: case REG_RST+3: + wait_fifo_idle(mystique); + mystique->busy = 0; + mystique->blitter_submit_refcount = 0; + mystique->blitter_submit_dma_refcount = 0; + mystique->blitter_complete_refcount = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->status = STATUS_ENDPRDMASTS; + break; + + case REG_ATTR_IDX: + svga_out(0x3c0, val, svga); + break; + case REG_ATTR_DATA: + svga_out(0x3c1, val, svga); + break; + + case REG_MISC: + svga_out(0x3c2, val, svga); + break; + + case REG_SEQ_IDX: + svga_out(0x3c4, val, svga); + break; + case REG_SEQ_DATA: + svga_out(0x3c5, val, svga); + break; + + case REG_GCTL_IDX: + mystique_out(0x3ce, val, mystique); + break; + case REG_GCTL_DATA: + mystique_out(0x3cf, val, mystique); + break; + + case REG_CRTC_IDX: + mystique_out(0x3d4, val, mystique); + break; + case REG_CRTC_DATA: + mystique_out(0x3d5, val, mystique); + break; + + case REG_CRTCEXT_IDX: + mystique_out(0x3de, val, mystique); + break; + case REG_CRTCEXT_DATA: + mystique_out(0x3df, val, mystique); + break; + + case REG_CACHEFLUSH: + break; + + case REG_PALWTADD: + svga_out(0x3c8, val, svga); + mystique->xreg_idx = val; + break; + case REG_PALDATA: + svga_out(0x3c9, val, svga); + break; + case REG_PIXRDMSK: + svga_out(0x3c6, val, svga); + break; + case REG_PALRDADD: + svga_out(0x3c7, val, svga); + break; + + case REG_X_DATAREG: + mystique_write_xreg(mystique, mystique->xreg_idx, val); + break; + + case REG_CURPOSX: case REG_CURPOSX+1: + WRITE8(addr, mystique->cursor.pos_x, val); + svga->hwcursor.x = mystique->cursor.pos_x - 64; + break; + case REG_CURPOSY: case REG_CURPOSY+1: + WRITE8(addr & 1, mystique->cursor.pos_y, val); + svga->hwcursor.y = mystique->cursor.pos_y - 64; + break; + + case 0x1e50: case 0x1e51: case 0x1e52: case 0x1e53: + case 0x3c0b: case 0x3e02: case 0x3e08: + break; + + default: + if ((addr & 0x3fff) >= 0x2c4c && (addr & 0x3fff) <= 0x2cff) + break; + if ((addr & 0x3fff) >= 0x3e00) + break; + break; + } +} + + +static uint32_t +mystique_ctrl_read_l(uint32_t addr, void *p) +{ + uint32_t ret; + + if ((addr & 0x3fff) < 0x1c00) + return mystique_iload_read_l(addr, p); + + ret = mystique_ctrl_read_b(addr, p); + ret |= mystique_ctrl_read_b(addr+1, p) << 8; + ret |= mystique_ctrl_read_b(addr+2, p) << 16; + ret |= mystique_ctrl_read_b(addr+3, p) << 24; + + return ret; +} + + +static void +mystique_accel_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + int start_blit = 0; + + if ((addr & 0x300) == 0x100) { + addr &= ~0x100; + start_blit = 1; + } + + switch (addr & 0x3ffc) { + case REG_DWGCTL: + mystique->dwgreg.dwgctrl = val; + break; + + case REG_ZORG: + mystique->dwgreg.zorg = val; + mystique->dwgreg.z_base = mystique->dwgreg.ydstorg*2 + mystique->dwgreg.zorg; + break; + + case REG_PLNWT: + mystique->dwgreg.plnwt = val; + break; + + case REG_SHIFT: + mystique->dwgreg.funcnt = val & 0xff; + mystique->dwgreg.xoff = val & 7; + mystique->dwgreg.yoff = (val >> 4) & 7; + mystique->dwgreg.stylelen = (val >> 16) & 0xff; + break; + + case REG_PITCH: + mystique->dwgreg.pitch = val & 0xffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + else + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + break; + + case REG_YDST: + mystique->dwgreg.ydst = val & 0x3fffff; + if (mystique->dwgreg.pitch & PITCH_YLIN) { + mystique->dwgreg.ydst_lin = (mystique->dwgreg.ydst << 5) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val >> 29; + } else { + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; + mystique->dwgreg.selline = val & 7; + } + break; + case REG_BCOL: + mystique->dwgreg.bcol = val; + break; + case REG_FCOL: + mystique->dwgreg.fcol = val; + break; + + case REG_SRC0: + mystique->dwgreg.src[0] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[0], 32); + break; + case REG_SRC1: + mystique->dwgreg.src[1] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[1], 32); + break; + case REG_SRC2: + mystique->dwgreg.src[2] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[2], 32); + break; + case REG_SRC3: + mystique->dwgreg.src[3] = val; + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[3], 32); + break; + + case REG_DMAPAD: + if ((mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) == DWGCTRL_OPCODE_ILOAD) + blit_iload_write(mystique, mystique->dwgreg.src[0], 32); + break; + + case REG_AR0: + mystique->dwgreg.ar[0] = val; + break; + case REG_AR1: + mystique->dwgreg.ar[1] = val; + break; + case REG_AR2: + mystique->dwgreg.ar[2] = val; + break; + case REG_AR3: + mystique->dwgreg.ar[3] = val; + break; + case REG_AR4: + mystique->dwgreg.ar[4] = val; + break; + case REG_AR5: + mystique->dwgreg.ar[5] = val; + break; + case REG_AR6: + mystique->dwgreg.ar[6] = val; + break; + + case REG_DR0: + mystique->dwgreg.dr[0] = val; + break; + case REG_DR2: + mystique->dwgreg.dr[2] = val; + break; + case REG_DR3: + mystique->dwgreg.dr[3] = val; + break; + case REG_DR4: + mystique->dwgreg.dr[4] = val; + break; + case REG_DR6: + mystique->dwgreg.dr[6] = val; + break; + case REG_DR7: + mystique->dwgreg.dr[7] = val; + break; + case REG_DR8: + mystique->dwgreg.dr[8] = val; + break; + case REG_DR10: + mystique->dwgreg.dr[10] = val; + break; + case REG_DR11: + mystique->dwgreg.dr[11] = val; + break; + case REG_DR12: + mystique->dwgreg.dr[12] = val; + break; + case REG_DR14: + mystique->dwgreg.dr[14] = val; + break; + case REG_DR15: + mystique->dwgreg.dr[15] = val; + break; + + case REG_SECEND: + mystique->dma.secend = val; + if (mystique->dma.state != DMA_STATE_SEC && (mystique->dma.secaddress & DMA_ADDR_MASK) != (mystique->dma.secend & DMA_ADDR_MASK)) + mystique->dma.state = DMA_STATE_SEC; + break; + + case REG_SOFTRAP: + mystique->dma.state = DMA_STATE_IDLE; + mystique->endprdmasts_pending = 1; + mystique->softrap_pending_val = val; + mystique->softrap_pending = 1; + break; + + default: + mystique_accel_ctrl_write_b(addr, val & 0xff, p); + mystique_accel_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_accel_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_accel_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } + + if (start_blit) + mystique_start_blit(mystique); +} + + +static void +mystique_ctrl_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + uint32_t reg_addr; + + if ((addr & 0x3fff) < 0x1c00) { + mystique_iload_write_l(addr, val, p); + return; + } + + if ((addr & 0x3e00) == 0x1c00 || (addr & 0x3e00) == 0x2c00) { + if ((addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + mystique_queue(mystique, addr & 0x3fff, val, FIFO_WRITE_CTRL_LONG); + return; + } + + switch (addr & 0x3ffc) { + case REG_PRIMEND: + thread_wait_mutex(mystique->dma.lock); + mystique->dma.primend = val; + if (mystique->dma.state == DMA_STATE_IDLE && (mystique->dma.primaddress & DMA_ADDR_MASK) != (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 0; + mystique->status &= ~STATUS_ENDPRDMASTS; + + mystique->dma.state = DMA_STATE_PRI; + mystique->dma.pri_state = 0; + wake_fifo_thread(mystique); + } + thread_release_mutex(mystique->dma.lock); + break; + + case REG_DWG_INDIR_WT: case REG_DWG_INDIR_WT+0x04: case REG_DWG_INDIR_WT+0x08: case REG_DWG_INDIR_WT+0x0c: + case REG_DWG_INDIR_WT+0x10: case REG_DWG_INDIR_WT+0x14: case REG_DWG_INDIR_WT+0x18: case REG_DWG_INDIR_WT+0x1c: + case REG_DWG_INDIR_WT+0x20: case REG_DWG_INDIR_WT+0x24: case REG_DWG_INDIR_WT+0x28: case REG_DWG_INDIR_WT+0x2c: + case REG_DWG_INDIR_WT+0x30: case REG_DWG_INDIR_WT+0x34: case REG_DWG_INDIR_WT+0x38: case REG_DWG_INDIR_WT+0x3c: + reg_addr = (mystique->dmamap[(addr >> 2) & 0xf] & 0x7f) << 2; + if (mystique->dmamap[(addr >> 2) & 0xf] & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_refcount++; + + mystique_queue(mystique, reg_addr, val, FIFO_WRITE_CTRL_LONG); + break; + + default: + mystique_ctrl_write_b(addr, val & 0xff, p); + mystique_ctrl_write_b(addr+1, (val >> 8) & 0xff, p); + mystique_ctrl_write_b(addr+2, (val >> 16) & 0xff, p); + mystique_ctrl_write_b(addr+3, (val >> 24) & 0xff, p); + break; + } +} + + +static uint8_t +mystique_iload_read_b(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xff; + + return blit_idump_read(mystique); +} + + +static uint32_t +mystique_iload_read_l(uint32_t addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + wait_fifo_idle(mystique); + + if (!mystique->busy) + return 0xffffffff; + + mystique->dwgreg.words++; + return blit_idump_read(mystique); +} + + +static void +mystique_iload_write_b(uint32_t addr, uint8_t val, void *p) +{ + +} + + +static void +mystique_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + mystique_queue(mystique, 0, val, FIFO_WRITE_ILOAD_LONG); +} + + +static void +mystique_accel_iload_write_l(uint32_t addr, uint32_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + switch (mystique->dwgreg.dmamod) { + case DMA_MODE_REG: + if (mystique->dma.iload_state == 0) { + mystique->dma.iload_header = val; + mystique->dma.iload_state = 1; + } else { + uint32_t reg_addr = (mystique->dma.iload_header & 0x7f) << 2; + if (mystique->dma.iload_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + + mystique->dma.iload_header >>= 8; + mystique->dma.iload_state = (mystique->dma.iload_state == 4) ? 0 : (mystique->dma.iload_state+1); + } + break; + + case DMA_MODE_BLIT: + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + blit_iload_write(mystique, val, 32); + break; + + /* default: + pclog("ILOAD write DMAMOD %i\n", mystique->dwgreg.dmamod); */ + } +} + + +static uint8_t +mystique_readb_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + + egareads++; + + sub_cycles(video_timing_read_b); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xff; + + return svga->vram[addr & svga->vram_mask]; +} + + +static uint16_t +mystique_readw_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + + egareads += 2; + + sub_cycles(video_timing_read_w); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffff; + + return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; +} + + +static uint32_t +mystique_readl_linear(uint32_t addr, void *p) +{ + svga_t *svga = (svga_t *)p; + + egareads += 4; + + sub_cycles(video_timing_read_l); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return 0xffffffff; + + return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; +} + + +static void +mystique_writeb_linear(uint32_t addr, uint8_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + egawrites++; + + sub_cycles(video_timing_write_b); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + svga->vram[addr] = val; +} + + +static void +mystique_writew_linear(uint32_t addr, uint16_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + egawrites += 2; + + sub_cycles(video_timing_write_w); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint16_t *)&svga->vram[addr] = val; +} + + +static void +mystique_writel_linear(uint32_t addr, uint32_t val, void *p) +{ + svga_t *svga = (svga_t *)p; + + egawrites += 4; + + sub_cycles(video_timing_write_l); + + addr &= svga->decode_mask; + if (addr >= svga->vram_max) + return; + addr &= svga->vram_mask; + svga->changedvram[addr >> 12] = changeframecount; + *(uint32_t *)&svga->vram[addr] = val; +} + + +static void +run_dma(mystique_t *mystique) +{ + int words_transferred = 0; + + thread_wait_mutex(mystique->dma.lock); + + if (mystique->dma.state == DMA_STATE_IDLE) { + thread_release_mutex(mystique->dma.lock); + return; + } + + while (words_transferred < DMA_MAX_WORDS && mystique->dma.state != DMA_STATE_IDLE) { + switch (mystique->dma.state) { + case DMA_STATE_PRI: + switch (mystique->dma.primaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.pri_state == 0) { + mystique->dma.pri_header = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; + mystique->dma.primaddress += 4; + } + + if ((mystique->dma.pri_header & 0xff) != 0x15) { + uint32_t val = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; + + mystique->dma.primaddress += 4; + + reg_addr = (mystique->dma.pri_header & 0x7f) << 2; + if (mystique->dma.pri_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + } + + mystique->dma.pri_header >>= 8; + mystique->dma.pri_state = (mystique->dma.pri_state + 1) & 3; + + words_transferred++; + if (mystique->dma.state == DMA_STATE_SEC) + mystique->dma.pri_state = 0; + else if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } + break; + + default: + fatal("DMA_STATE_PRI: mode %i\n", mystique->dma.primaddress & DMA_MODE_MASK); + } + break; + + case DMA_STATE_SEC: + switch (mystique->dma.secaddress & DMA_MODE_MASK) { + case DMA_MODE_REG: + if (mystique->dma.sec_state == 0) { + mystique->dma.sec_header = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + mystique->dma.secaddress += 4; + } + + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + uint32_t reg_addr; + + mystique->dma.secaddress += 4; + + reg_addr = (mystique->dma.sec_header & 0x7f) << 2; + if (mystique->dma.sec_header & 0x80) + reg_addr += 0x2c00; + else + reg_addr += 0x1c00; + + if ((reg_addr & 0x300) == 0x100) + mystique->blitter_submit_dma_refcount++; + + mystique_accel_ctrl_write_l(reg_addr, val, mystique); + + mystique->dma.sec_header >>= 8; + mystique->dma.sec_state = (mystique->dma.sec_state + 1) & 3; + + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + break; + + case DMA_MODE_BLIT: { + uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK]; + mystique->dma.secaddress += 4; + + if (!mystique->busy) + fatal("mystique_iload_write_l: !busy\n"); + + blit_iload_write(mystique, val, 32); + + words_transferred++; + if ((mystique->dma.secaddress & DMA_ADDR_MASK) == (mystique->dma.secend & DMA_ADDR_MASK)) { + if ((mystique->dma.primaddress & DMA_ADDR_MASK) == (mystique->dma.primend & DMA_ADDR_MASK)) { + mystique->endprdmasts_pending = 1; + mystique->dma.state = DMA_STATE_IDLE; + } else + mystique->dma.state = DMA_STATE_PRI; + } + } break; + + default: + fatal("DMA_STATE_SEC: mode %i\n", mystique->dma.secaddress & DMA_MODE_MASK); + } + break; + } + } + + thread_release_mutex(mystique->dma.lock); +} + + +static void +fifo_thread(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + while (1) { + thread_set_event(mystique->fifo_not_full_event); + thread_wait_event(mystique->wake_fifo_thread, -1); + thread_reset_event(mystique->wake_fifo_thread); + + while (!FIFO_EMPTY || mystique->dma.state != DMA_STATE_IDLE) { + int words_transferred = 0; + + while (!FIFO_EMPTY && words_transferred < 100) { + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) { + case FIFO_WRITE_CTRL_BYTE: + mystique_accel_ctrl_write_b(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_CTRL_LONG: + mystique_accel_ctrl_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + case FIFO_WRITE_ILOAD_LONG: + mystique_accel_iload_write_l(fifo->addr_type & FIFO_ADDR, fifo->val, mystique); + break; + } + + fifo->addr_type = FIFO_INVALID; + mystique->fifo_read_idx++; + + if (FIFO_ENTRIES > FIFO_THRESHOLD) + thread_set_event(mystique->fifo_not_full_event); + + words_transferred++; + } + + /*Only run DMA once the FIFO is empty. Required by + Screamer 2 / Rally which will incorrectly clip an ILOAD + if DMA runs ahead*/ + if (!words_transferred) + run_dma(mystique); + } + } +} + + +static void +wake_fifo_thread(mystique_t *mystique) +{ + if (!timer_is_enabled(&mystique->wake_timer)) { + /* Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work. */ + timer_set_delay_u64(&mystique->wake_timer, WAKE_DELAY); + } +} + + +static void +wake_fifo_thread_now(mystique_t *mystique) +{ + thread_set_event(mystique->wake_fifo_thread); +} + + +static void +mystique_wake_timer(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + thread_set_event(mystique->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + + +static void +wait_fifo_idle(mystique_t *mystique) +{ + while (!FIFO_EMPTY) { + wake_fifo_thread_now(mystique); + thread_wait_event(mystique->fifo_not_full_event, 1); + } +} + + +/*IRQ code (PCI & PIC) is not currently thread safe. SOFTRAP IRQ requests must + therefore be submitted from the main emulation thread, in this case via a timer + callback. End-of-DMA status is also deferred here to prevent races between + SOFTRAP IRQs and code reading the status register. Croc will get into an IRQ + loop and triple fault if the ENDPRDMASTS flag is seen before the IRQ is taken*/ +static void mystique_softrap_pending_timer(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + timer_advance_u64(&mystique->softrap_pending_timer, TIMER_USEC * 100); + + if (mystique->endprdmasts_pending) { + mystique->endprdmasts_pending = 0; + mystique->status |= STATUS_ENDPRDMASTS; + } + if (mystique->softrap_pending) { + mystique->softrap_pending = 0; + + mystique->dma.secaddress = mystique->softrap_pending_val; + mystique->status |= STATUS_SOFTRAPEN; + mystique_update_irqs(mystique); + } +} + + +static +void mystique_queue(mystique_t *mystique, uint32_t addr, uint32_t val, uint32_t type) +{ + fifo_entry_t *fifo = &mystique->fifo[mystique->fifo_write_idx & FIFO_MASK]; + + if (FIFO_FULL) { + thread_reset_event(mystique->fifo_not_full_event); + if (FIFO_FULL) + thread_wait_event(mystique->fifo_not_full_event, -1); /* Wait for room in ringbuffer */ + } + + fifo->val = val; + fifo->addr_type = (addr & FIFO_ADDR) | type; + + mystique->fifo_write_idx++; + + if (FIFO_ENTRIES > FIFO_THRESHOLD || FIFO_ENTRIES < 8) + wake_fifo_thread(mystique); +} + + +static uint32_t +bitop(uint32_t src, uint32_t dst, uint32_t dwgctrl) +{ + switch (dwgctrl & DWGCTRL_BOP_MASK) { + case BOP(0x0): return 0; + case BOP(0x1): return ~(dst | src); + case BOP(0x2): return dst & ~src; + case BOP(0x3): return ~src; + case BOP(0x4): return ~dst & src; + case BOP(0x5): return ~dst; + case BOP(0x6): return dst ^ src; + case BOP(0x7): return ~(dst & src); + case BOP(0x8): return dst & src; + case BOP(0x9): return ~(dst ^ src); + case BOP(0xa): return dst; + case BOP(0xb): return dst | ~src; + case BOP(0xc): return src; + case BOP(0xd): return ~dst | src; + case BOP(0xe): return dst | src; + case BOP(0xf): return ~0; + } + + return 0; +} + + +static uint16_t +dither(mystique_t *mystique, int r, int g, int b, int x, int y) +{ + switch (mystique->dwgreg.dither) { + case DITHER_NONE_555: + return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10); + + case DITHER_NONE_565: + return (b >> 3) | ((g >> 2) << 5) | ((r >> 3) << 11); + + case DITHER_555: + return dither5[b][y][x] | (dither5[g][y][x] << 5) | (dither5[r][y][x] << 10); + + case DITHER_565: + default: + return dither5[b][y][x] | (dither6[g][y][x] << 5) | (dither5[r][y][x] << 11); + } +} + + +static uint32_t +blit_idump_idump(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint64_t val64 = 0; + uint32_t val = 0; + int count = 0; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BU32RGB: + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + while (count < 32) { + val |= (svga->vram[mystique->dwgreg.src_addr & mystique->vram_mask] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 8; + } + break; + + case MACCESS_PWIDTH_16: + while (count < 32) { + val |= (((uint16_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_w] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 16; + } + break; + + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.idump_end_of_line) { + mystique->dwgreg.idump_end_of_line = 0; + val = mystique->dwgreg.iload_rem_data; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + + count += mystique->dwgreg.iload_rem_count; + val64 = mystique->dwgreg.iload_rem_data; + + while ((count < 32) && !mystique->dwgreg.idump_end_of_line) { + val64 |= (uint64_t)((*(uint32_t *)&svga->vram[(mystique->dwgreg.src_addr * 3) & mystique->vram_mask]) & 0xffffff) << count; + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) { + if (count > 8) + mystique->dwgreg.idump_end_of_line = 1; + else { + count = 32; + break; + } + } + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + + count += 24; + } + if (count > 32) + mystique->dwgreg.iload_rem_count = count - 32; + else + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = (uint32_t)(val64 >> 32); + val = val64 & 0xffffffff; + break; + + case MACCESS_PWIDTH_32: + val = (((uint32_t *)svga->vram)[mystique->dwgreg.src_addr & mystique->vram_mask_l] << count); + + if (mystique->dwgreg.src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + } else + mystique->dwgreg.src_addr++; + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + break; + + default: + fatal("IDUMP DWGCTRL_BLTMOD_BU32RGB %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->maccess_running); + } + break; + + default: + fatal("IDUMP DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + return val; +} + + +static uint32_t +blit_idump_read(mystique_t *mystique) +{ + uint32_t ret = 0xffffffff; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_IDUMP: + ret = blit_idump_idump(mystique); + break; + + default: + /* pclog("blit_idump_read: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); */ + break; + } + + return ret; +} + + +static void +blit_iload_iload(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint32_t src, dst; + uint32_t dst2; + uint64_t data64; + int min_size = 8; + uint32_t bltckey = mystique->dwgreg.fcol, bltcmsk = mystique->dwgreg.bcol; + const int transc = mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + bltckey &= 0xff; + bltcmsk &= 0xff; + break; + case MACCESS_PWIDTH_16: + bltckey &= 0xffff; + bltcmsk &= 0xffff; + break; + } + + mystique->dwgreg.words++; + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + while ((mystique->dwgreg.length_cur > 0) && (size >= 16)) { + uint16_t src = data & 0xffff; + + mystique->lut[mystique->dwgreg.ydst & 0xff].r = (src >> 11) << 3; + mystique->lut[mystique->dwgreg.ydst & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[mystique->dwgreg.ydst & 0xff].b = (src & 0x1f) << 3; + mystique->dwgreg.ydst++; + mystique->dwgreg.length_cur--; + data >>= 16; + size -= 16; + } + + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + min_size = 8; + break; + case MACCESS_PWIDTH_16: + min_size = 16; + break; + case MACCESS_PWIDTH_24: + min_size = 24; + break; + case MACCESS_PWIDTH_32: + min_size = 32; + break; + } + + while (size >= min_size) { + int draw = (!transc || (data & bltcmsk) != bltckey) && trans[mystique->dwgreg.xdst & 3]; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(data & 0xff, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + } + + data >>= 8; + size -= 8; + break; + + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } + + data >>= 16; + size -= 16; + break; + + case MACCESS_PWIDTH_24: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t old_dst = *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]); + + dst = bitop(data64, old_dst, mystique->dwgreg.dwgctrl_running); + *((uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]) = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + } + + data64 >>= 24; + size -= 24; + break; + + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && draw) { + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + size = 0; + break; + + default: + fatal("ILOAD RSTR/RPL BFCOL pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + case DWGCTRL_BLTMOD_BMONOWF: + data = (data >> 24) | ((data & 0x00ff0000) >> 8) | ((data & 0x0000ff00) << 8) | (data << 24); + while (size) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((data & 0x80000000) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[mystique->dwgreg.xdst & 3]) { + uint32_t old_dst; + + src = (data & 0x80000000) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + svga->vram[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BMONOWF pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + if (!(mystique->dwgreg.dwgctrl_running & DWGCTRL_LINEAR)) + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + data <<= 1; + size--; + } + break; + + case DWGCTRL_BLTMOD_BU24RGB: + size += mystique->dwgreg.iload_rem_count; + data64 = mystique->dwgreg.iload_rem_data | ((uint64_t)data << mystique->dwgreg.iload_rem_count); + + while (size >= 24) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(data64 & 0xffffff, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BU24RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + data64 >>= 24; + size -= 24; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + data64 = 0; + size = 0; + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + + mystique->dwgreg.iload_rem_count = size; + mystique->dwgreg.iload_rem_data = data64; + break; + + case DWGCTRL_BLTMOD_BU32RGB: + size += mystique->dwgreg.iload_rem_count; + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + + dst = bitop(data, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BU32RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + size = 0; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + + mystique->dwgreg.iload_rem_count = size; + break; + + case DWGCTRL_BLTMOD_BU32BGR: + size += mystique->dwgreg.iload_rem_count; + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst2 = ((dst >> 16) & 0xff) | (dst & 0xff00) | ((dst & 0xff) << 16); /* BGR to RGB */ + + dst = bitop(data, dst2, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD RSTR/RPL BU32RGB pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + size = 0; + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + + mystique->dwgreg.iload_rem_count = size; + break; + + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL\n"); + break; + } + break; + + default: + fatal("Unknown ILOAD iload atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +#define CLAMP(x) do { \ + if ((x) & ~0xff) \ + x = ((x) < 0) ? 0 : 0xff; \ + } while (0) + + +static void +blit_iload_iload_scale(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint64_t data64 = 0; + int y0, y1; + int u, v; + int dR, dG, dB; + int r0, g0, b0; + int r1, g1, b1; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; + + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; + + r0 = y0 + dR; + CLAMP(r0); + g0 = y0 - dG; + CLAMP(g0); + b0 = y0 + dB; + CLAMP(b0); + r1 = y1 + dR; + CLAMP(r1); + g1 = y1 - dG; + CLAMP(g1); + b1 = y1 + dB; + CLAMP(b1); + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + data = (b0 >> 3) | ((g0 >> 2) << 5) | ((r0 >> 3) << 11); + data |= (((b1 >> 3) | ((g1 >> 2) << 5) | ((r1 >> 3) << 11)) << 16); + size = 32; + break; + case MACCESS_PWIDTH_32: + data64 = b0 | (g0 << 8) | (r0 << 16); + data64 |= ((uint64_t)b0 << 32) | ((uint64_t)g0 << 40) | ((uint64_t)r0 << 48); + size = 64; + break; + + default: + fatal("blit_iload_iload_scale BUYUV pwidth %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + break; + + default: + fatal("blit_iload_iload_scale bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(data & 0xffff, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data >>= 16; + size -= 16; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + break; + + case MACCESS_PWIDTH_32: + while (size >= 32) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(data64, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + data64 >>= 32; + size -= 32; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } + break; + + default: + fatal("ILOAD_SCALE pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } +} + + +static void +blit_iload_iload_high(mystique_t *mystique, uint32_t data, int size) +{ + svga_t *svga = &mystique->svga; + uint32_t out_data; + int y0, y1, u, v; + int dR, dG, dB; + int r = 0, g = 0, b = 0; + int next_r = 0, next_g = 0, next_b = 0; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + y0 = (298 * ((int)(data & 0xff) - 16)) >> 8; + u = ((data >> 8) & 0xff) - 0x80; + y1 = (298 * ((int)((data >> 16) & 0xff) - 16)) >> 8; + v = ((data >> 24) & 0xff) - 0x80; + + dR = (309*v) >> 8; + dG = (100*u + 208*v) >> 8; + dB = (516*u) >> 8; + + r = y0 + dR; + CLAMP(r); + g = y0 - dG; + CLAMP(g); + b = y0 + dB; + CLAMP(b); + + next_r = y1 + dR; + CLAMP(next_r); + next_g = y1 - dG; + CLAMP(next_g); + next_b = y1 + dB; + CLAMP(next_b); + + size = 32; + break; + + case DWGCTRL_BLTMOD_BU32BGR: + r = ((data >> 16) & 0xff); + CLAMP(r); + g = ((data >> 8) & 0xff); + CLAMP(g); + b = (data & 0xff); + CLAMP(b); + + next_r = r; + next_g = g; + next_b = b; + + size = 32; + break; + + default: + fatal("blit_iload_iload_high bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + + while (size >= 16) { + if (mystique->dwgreg.xdst >= mystique->dwgreg.cxleft && mystique->dwgreg.xdst <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t dst; + int f1 = (mystique->dwgreg.ar[6] >> 12) & 0xf; + int f0 = 0x10 - f1; + int out_r = ((mystique->dwgreg.lastpix_r * f0) + (r * f1)) >> 4; + int out_g = ((mystique->dwgreg.lastpix_g * f0) + (g * f1)) >> 4; + int out_b = ((mystique->dwgreg.lastpix_b * f0) + (b * f1)) >> 4; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + out_data = (out_b >> 3) | ((out_g >> 2) << 5) | ((out_r >> 3) << 11); + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + case MACCESS_PWIDTH_32: + out_data = out_b | (out_g << 8) | (out_r << 16); + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l]; + dst = bitop(out_data, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + mystique->dwgreg.xdst) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("ILOAD_SCALE_HIGH RSTR/RPL BUYUV pwidth %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + mystique->dwgreg.ar[6] += mystique->dwgreg.ar[2]; + if ((int32_t)mystique->dwgreg.ar[6] >= 0) { + mystique->dwgreg.ar[6] -= 65536; + size -= 16; + + mystique->dwgreg.lastpix_r = r; + mystique->dwgreg.lastpix_g = g; + mystique->dwgreg.lastpix_b = b; + r = next_r; + g = next_g; + b = next_b; + } + + if (mystique->dwgreg.xdst == mystique->dwgreg.fxright) { + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + mystique->dwgreg.ar[6] = mystique->dwgreg.ar[2] - (mystique->dwgreg.fxright - mystique->dwgreg.fxleft); + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + + mystique->dwgreg.length_cur--; + if (!mystique->dwgreg.length_cur) { + mystique->busy = 0; + mystique->blitter_complete_refcount++; + break; + } + break; + } else + mystique->dwgreg.xdst = (mystique->dwgreg.xdst + 1) & 0xffff; + } +} + + +static void +blit_iload_iload_highv(mystique_t *mystique, uint32_t data, int size) +{ + uint8_t *src0, *src1; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + if (!mystique->dwgreg.highv_line) { + mystique->dwgreg.highv_data = data; + mystique->dwgreg.highv_line = 1; + return; + } + mystique->dwgreg.highv_line = 0; + + src0 = (uint8_t *)&mystique->dwgreg.highv_data; + src1 = (uint8_t *)&data; + + src1[0] = ((src0[0] * mystique->dwgreg.beta) + (src1[0] * (16 - mystique->dwgreg.beta))) >> 4; + src1[1] = ((src0[1] * mystique->dwgreg.beta) + (src1[1] * (16 - mystique->dwgreg.beta))) >> 4; + src1[2] = ((src0[2] * mystique->dwgreg.beta) + (src1[2] * (16 - mystique->dwgreg.beta))) >> 4; + src1[3] = ((src0[3] * mystique->dwgreg.beta) + (src1[3] * (16 - mystique->dwgreg.beta))) >> 4; + blit_iload_iload_high(mystique, data, 32); + break; + + default: + fatal("blit_iload_iload_highv bltmod %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } +} + + +static void +blit_iload_write(mystique_t *mystique, uint32_t data, int size) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_ILOAD: + blit_iload_iload(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_iload_scale(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_iload_high(mystique, data, size); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_iload_highv(mystique, data, size); + break; + + default: + fatal("blit_iload_write: bad opcode %08x\n", mystique->dwgreg.dwgctrl_running); + } +} + + +static int +z_check(uint16_t z, uint16_t old_z, uint32_t z_mode)//mystique->dwgreg.dwgctrl & DWGCTRL_ZMODE_MASK) +{ + switch (z_mode) { + case DWGCTRL_ZMODE_ZE: + return (z == old_z); + case DWGCTRL_ZMODE_ZNE: + return (z != old_z); + case DWGCTRL_ZMODE_ZLT: + return (z < old_z); + case DWGCTRL_ZMODE_ZLTE: + return (z <= old_z); + case DWGCTRL_ZMODE_ZGT: + return (z > old_z); + case DWGCTRL_ZMODE_ZGTE: + return (z >= old_z); + + case DWGCTRL_ZMODE_NOZCMP: + default: + return 1; + } +} + + +static void +blit_line(mystique_t *mystique, int closed) +{ + svga_t *svga = &mystique->svga; + uint32_t src, dst, old_dst; + int x; + int z_write; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_RPL: + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = mystique->dwgreg.fcol; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = mystique->dwgreg.fcol; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = mystique->dwgreg.fcol; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = mystique->dwgreg.fcol; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("LINE RSTR/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + x = mystique->dwgreg.xdst; + while (mystique->dwgreg.length > 0) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + uint16_t old_z = z_p[x]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int r = 0, g = 0, b = 0; + + if (z_write) + z_p[x] = z; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_16: + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 18) & 0x1f; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 17) & 0x3f; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 18) & 0x1f; + dst = (r << 11) | (g << 5) | b; + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + default: + fatal("LINE I/ZI PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } + + if (mystique->dwgreg.sgn.sdydxl) + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + + if ((int32_t)mystique->dwgreg.ar[1] >= 0) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if (mystique->dwgreg.sgn.sdydxl) + mystique->dwgreg.ydst_lin += (mystique->dwgreg.sgn.sdy ? -(mystique->dwgreg.pitch & PITCH_MASK) : (mystique->dwgreg.pitch & PITCH_MASK)); + else + x += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[15]; + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + + mystique->dwgreg.length--; + } + break; + + default: + /* pclog("Unknown atype %03x %08x LINE\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); */ + break; + } + + mystique->blitter_complete_refcount++; +} + + +static void +blit_autoline(mystique_t *mystique, int closed) +{ + int start_x = (int32_t)mystique->dwgreg.ar[5]; + int start_y = (int32_t)mystique->dwgreg.ar[6]; + int end_x = (int32_t)mystique->dwgreg.ar[0]; + int end_y = (int32_t)mystique->dwgreg.ar[2]; + int dx = end_x - start_x; + int dy = end_y - start_y; + + if (ABS(dx) > ABS(dy)) { + mystique->dwgreg.sgn.sdydxl = 1; + mystique->dwgreg.ar[0] = 2*ABS(dy); + mystique->dwgreg.ar[1] = 2*ABS(dy) - ABS(dx) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dy) - 2*ABS(dx); + mystique->dwgreg.length = ABS(end_x - start_x); + } else { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.ar[0] = 2*ABS(dx); + mystique->dwgreg.ar[1] = 2*ABS(dx) - ABS(dy) - ((start_y > end_y) ? 1 : 0); + mystique->dwgreg.ar[2] = 2*ABS(dx) - 2*ABS(dy); + mystique->dwgreg.length = ABS(end_y - start_y); + } + mystique->dwgreg.sgn.sdxl = (start_x > end_x) ? 1 : 0; + mystique->dwgreg.sgn.sdy = (start_y > end_y) ? 1 : 0; + + blit_line(mystique, closed); + + mystique->dwgreg.ar[5] = end_x; + mystique->dwgreg.xdst = end_x; + mystique->dwgreg.ar[6] = end_y; + mystique->dwgreg.ydst = end_y; + mystique->dwgreg.ydst_lin = ((int32_t)(int16_t)mystique->dwgreg.ydst * (mystique->dwgreg.pitch & PITCH_MASK)) + mystique->dwgreg.ydstorg; +} + + +static void +blit_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t z_back, r_back, g_back, b_back; + int z_write; + int y; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_BLK: + case DWGCTRL_ATYPE_RPL: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = + (pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffff; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = + ((pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff) | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = + pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l++; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_RSTR: + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int yoff = (mystique->dwgreg.yoff + mystique->dwgreg.ydst) & 7; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + int xoff = (mystique->dwgreg.xoff + x_l) & 7; + int pattern = mystique->dwgreg.pattern[yoff][xoff]; + uint32_t src = pattern ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP RSTR PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + x_l++; + mystique->pixel_count++; + } + + if ((int32_t)mystique->dwgreg.ar[1] < 0) { + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + } else + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + if ((int32_t)mystique->dwgreg.ar[4] < 0) { + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + } else + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int16_t old_x_l = x_l; + int dx; + + z_back = mystique->dwgreg.dr[0]; + r_back = mystique->dwgreg.dr[4]; + g_back = mystique->dwgreg.dr[8]; + b_back = mystique->dwgreg.dr[12]; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + uint32_t dst = 0, old_dst; + int r = 0, g = 0, b = 0; + + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + + if (z_write) + z_p[x_l] = z; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + svga->vram[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = dither(mystique, r, g, b, x_l & 1, mystique->dwgreg.selline & 1); + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) & 0xff000000; + *(uint32_t *)(&svga->vram[((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask]) = old_dst | dst; + svga->changedvram[(((mystique->dwgreg.ydst_lin + x_l) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = b | (g << 8) | (r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("TRAP BLK/RPL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + } + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + + x_l++; + mystique->pixel_count++; + } + + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + + +static int texture_read(mystique_t *mystique, int *tex_r, int *tex_g, int *tex_b, int *atransp) +{ + svga_t *svga = &mystique->svga; + + const int tex_shift = 3 + ((mystique->dwgreg.texctl & TEXCTL_TPITCH_MASK) >> TEXCTL_TPITCH_SHIFT); + const unsigned int palsel = mystique->dwgreg.texctl & TEXCTL_PALSEL_MASK; + const uint16_t tckey = mystique->dwgreg.textrans & TEXTRANS_TCKEY_MASK; + const uint16_t tkmask = (mystique->dwgreg.textrans & TEXTRANS_TKMASK_MASK) >> TEXTRANS_TKMASK_SHIFT; + const unsigned int w_mask = (mystique->dwgreg.texwidth & TEXWIDTH_TWMASK_MASK) >> TEXWIDTH_TWMASK_SHIFT; + const unsigned int h_mask = (mystique->dwgreg.texheight & TEXHEIGHT_THMASK_MASK) >> TEXHEIGHT_THMASK_SHIFT; + uint16_t src = 0; + int s, t; + + if (mystique->dwgreg.texctl & TEXCTL_NPCEN) { + const int s_shift = 20 - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = 20 - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + + s = (int32_t)mystique->dwgreg.tmr[6] >> s_shift; + t = (int32_t)mystique->dwgreg.tmr[7] >> t_shift; + } else { + const int s_shift = (20 + 16) - (mystique->dwgreg.texwidth & TEXWIDTH_TW_MASK); + const int t_shift = (20 + 16) - (mystique->dwgreg.texheight & TEXHEIGHT_TH_MASK); + int64_t q = mystique->dwgreg.tmr[8] ? ((0x100000000ll / (int64_t)(int32_t)mystique->dwgreg.tmr[8]) /*>> 16*/) : 0; + + s = (((int64_t)(int32_t)mystique->dwgreg.tmr[6] * q) /*<< 8*/) >> s_shift;/*((16+20)-12);*/ + t = (((int64_t)(int32_t)mystique->dwgreg.tmr[7] * q) /*<< 8*/) >> t_shift;/*((16+20)-9);*/ + } + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPU) { + if (s < 0) + s = 0; + else if (s > w_mask) + s = w_mask; + } else + s &= w_mask; + + if (mystique->dwgreg.texctl & TEXCTL_CLAMPV) { + if (t < 0) + t = 0; + else if (t > h_mask) + t = h_mask; + } else + t &= h_mask; + + switch (mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK) { + case TEXCTL_TEXFORMAT_TW4: + src = svga->vram[(mystique->dwgreg.texorg + (((t << tex_shift) + s) >> 1)) & mystique->vram_mask]; + if (s & 1) + src >>= 4; + else + src &= 0xf; + *tex_r = mystique->lut[src | palsel].r; + *tex_g = mystique->lut[src | palsel].g; + *tex_b = mystique->lut[src | palsel].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW8: + src = svga->vram[(mystique->dwgreg.texorg + (t << tex_shift) + s) & mystique->vram_mask]; + *tex_r = mystique->lut[src].r; + *tex_g = mystique->lut[src].g; + *tex_b = mystique->lut[src].b; + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW15: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = ((src >> 10) & 0x1f) << 3; + *tex_g = ((src >> 5) & 0x1f) << 3; + *tex_b = (src & 0x1f) << 3; + if (((src >> 15) & mystique->dwgreg.ta_mask) == mystique->dwgreg.ta_key) + *atransp = 1; + else + *atransp = 0; + break; + case TEXCTL_TEXFORMAT_TW16: + src = ((uint16_t *)svga->vram)[((mystique->dwgreg.texorg >> 1) + (t << tex_shift) + s) & mystique->vram_mask_w]; + *tex_r = (src >> 11) << 3; + *tex_g = ((src >> 5) & 0x3f) << 2; + *tex_b = (src & 0x1f) << 3; + *atransp = 0; + break; + default: + fatal("Unknown texture format %i\n", mystique->dwgreg.texctl & TEXCTL_TEXFORMAT_MASK); + break; + } + + return ((src & tkmask) == tckey); +} + + +static void +blit_texture_trap(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + int y; + int z_write; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + const int dest32 = ((mystique->maccess_running & MACCESS_PWIDTH_MASK) == MACCESS_PWIDTH_32); + + mystique->trap_count++; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_I: + case DWGCTRL_ATYPE_ZI: + z_write = ((mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) == DWGCTRL_ATYPE_ZI); + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint16_t *z_p = (uint16_t *)&svga->vram[(mystique->dwgreg.ydst_lin*2 + mystique->dwgreg.zorg) & mystique->vram_mask]; + int16_t x_l = mystique->dwgreg.fxleft & 0xffff; + int16_t x_r = mystique->dwgreg.fxright & 0xffff; + int16_t old_x_l = x_l; + int dx; + + uint32_t z_back = mystique->dwgreg.dr[0]; + uint32_t r_back = mystique->dwgreg.dr[4]; + uint32_t g_back = mystique->dwgreg.dr[8]; + uint32_t b_back = mystique->dwgreg.dr[12]; + uint32_t s_back = mystique->dwgreg.tmr[6]; + uint32_t t_back = mystique->dwgreg.tmr[7]; + uint32_t q_back = mystique->dwgreg.tmr[8]; + + while (x_l != x_r) { + if (x_l >= mystique->dwgreg.cxleft && x_l <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x_l & 3]) { + uint16_t z = ((int32_t)mystique->dwgreg.dr[0] < 0) ? 0 : (mystique->dwgreg.dr[0] >> 15); + uint16_t old_z = z_p[x_l]; + + if (z_check(z, old_z, mystique->dwgreg.dwgctrl_running & DWGCTRL_ZMODE_MASK)) { + int tex_r = 0, tex_g = 0, tex_b = 0; + int ctransp, atransp = 0; + int i_r = 0, i_g = 0, i_b = 0; + + if (!(mystique->dwgreg.dr[4] & (1 << 23))) + i_r = (mystique->dwgreg.dr[4] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[8] & (1 << 23))) + i_g = (mystique->dwgreg.dr[8] >> 15) & 0xff; + if (!(mystique->dwgreg.dr[12] & (1 << 23))) + i_b = (mystique->dwgreg.dr[12] >> 15) & 0xff; + + ctransp = texture_read(mystique, &tex_r, &tex_g, &tex_b, &atransp); + + switch (mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)) { + case 0: + if (ctransp) + goto skip_pixel; + if (atransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case TEXCTL_DECALCKEY: + if (ctransp) { + tex_r = i_r; + tex_g = i_g; + tex_b = i_b; + } + break; + + case (TEXCTL_STRANS | TEXCTL_DECALCKEY): + if (ctransp) + goto skip_pixel; + break; + + case TEXCTL_TMODULATE: + if (ctransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; + + case (TEXCTL_TMODULATE | TEXCTL_STRANS): + if (ctransp || atransp) + goto skip_pixel; + if (mystique->dwgreg.texctl & TEXCTL_TMODULATE) { + tex_r = (tex_r * i_r) >> 8; + tex_g = (tex_g * i_g) >> 8; + tex_b = (tex_b * i_b) >> 8; + } + break; + + default: + fatal("Bad TEXCTL %08x %08x\n", mystique->dwgreg.texctl, mystique->dwgreg.texctl & (TEXCTL_TMODULATE | TEXCTL_STRANS | TEXCTL_ITRANS | TEXCTL_DECALCKEY)); + } + + if (dest32) { + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l] = tex_b | (tex_g << 8) | (tex_r << 16); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_l) >> 10] = changeframecount; + } else { + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w] = dither(mystique, tex_r, tex_g, tex_b, x_l & 1, mystique->dwgreg.selline & 1); + svga->changedvram[((mystique->dwgreg.ydst_lin + x_l) & mystique->vram_mask_w) >> 11] = changeframecount; + } + if (z_write) + z_p[x_l] = z; + } + } +skip_pixel: + x_l++; + mystique->pixel_count++; + + mystique->dwgreg.dr[0] += mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += mystique->dwgreg.tmr[4]; + } + + mystique->dwgreg.dr[0] = z_back + mystique->dwgreg.dr[3]; + mystique->dwgreg.dr[4] = r_back + mystique->dwgreg.dr[7]; + mystique->dwgreg.dr[8] = g_back + mystique->dwgreg.dr[11]; + mystique->dwgreg.dr[12] = b_back + mystique->dwgreg.dr[15]; + mystique->dwgreg.tmr[6] = s_back + mystique->dwgreg.tmr[1]; + mystique->dwgreg.tmr[7] = t_back + mystique->dwgreg.tmr[3]; + mystique->dwgreg.tmr[8] = q_back + mystique->dwgreg.tmr[5]; + + while ((int32_t)mystique->dwgreg.ar[1] < 0 && mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[0]; + mystique->dwgreg.fxleft += (mystique->dwgreg.sgn.sdxl ? -1 : 1); + } + mystique->dwgreg.ar[1] += mystique->dwgreg.ar[2]; + + while ((int32_t)mystique->dwgreg.ar[4] < 0 && mystique->dwgreg.ar[6]) { + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[6]; + mystique->dwgreg.fxright += (mystique->dwgreg.sgn.sdxr ? -1 : 1); + } + mystique->dwgreg.ar[4] += mystique->dwgreg.ar[5]; + + dx = (int16_t)((mystique->dwgreg.fxleft - old_x_l) & 0xffff); + mystique->dwgreg.dr[0] += dx*mystique->dwgreg.dr[2]; + mystique->dwgreg.dr[4] += dx*mystique->dwgreg.dr[6]; + mystique->dwgreg.dr[8] += dx*mystique->dwgreg.dr[10]; + mystique->dwgreg.dr[12] += dx*mystique->dwgreg.dr[14]; + mystique->dwgreg.tmr[6] += dx*mystique->dwgreg.tmr[0]; + mystique->dwgreg.tmr[7] += dx*mystique->dwgreg.tmr[2]; + mystique->dwgreg.tmr[8] += dx*mystique->dwgreg.tmr[4]; + + mystique->dwgreg.ydst++; + mystique->dwgreg.ydst &= 0x7fffff; + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + + mystique->dwgreg.selline = (mystique->dwgreg.selline + 1) & 7; + } + break; + + default: + fatal("Unknown atype %03x %08x TEXTURE_TRAP\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } + + mystique->blitter_complete_refcount++; +} + + +static void +blit_bitblt(mystique_t *mystique) +{ + svga_t *svga = &mystique->svga; + uint32_t src_addr; + int y; + int x_dir = mystique->dwgreg.sgn.scanleft ? -1 : 1; + int16_t x_start = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxright : mystique->dwgreg.fxleft; + int16_t x_end = mystique->dwgreg.sgn.scanleft ? mystique->dwgreg.fxleft : mystique->dwgreg.fxright; + const int trans_sel = (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANS_MASK) >> DWGCTRL_TRANS_SHIFT; + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_BLK: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) { + int16_t x = x_start; + + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + uint32_t old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = mystique->dwgreg.fcol; + } else + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = mystique->dwgreg.fcol; + } else + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (mystique->dwgreg.fcol & 0xffffff); + } else + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = + (old_dst & 0xff000000) | (((svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol) & 0xffffff); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC) { + if (svga->vram[byte_addr] & (1 << bit_offset)) + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = mystique->dwgreg.fcol; + } else + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = + (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 11] = changeframecount; + break; + + default: + fatal("BITBLT DWGCTRL_ATYPE_BLK unknown MACCESS %i\n", mystique->maccess_running & MACCESS_PWIDTH_MASK); + } + } + + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; + + if (x != x_end) + x += x_dir; + else + break; + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + default: + fatal("BITBLT BLK %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); + break; + } + break; + + case DWGCTRL_ATYPE_RPL: + if (mystique->maccess_running & MACCESS_TLUTLOAD) { + src_addr = mystique->dwgreg.ar[3]; + + y = mystique->dwgreg.ydst; + + while (mystique->dwgreg.length) { + uint16_t src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + + mystique->lut[y & 0xff].r = (src >> 11) << 3; + mystique->lut[y & 0xff].g = ((src >> 5) & 0x3f) << 2; + mystique->lut[y & 0xff].b = (src & 0x1f) << 3; + src_addr++; + y++; + mystique->dwgreg.length--; + } + break; + } + case DWGCTRL_ATYPE_RSTR: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BMONOLEF: + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + fatal("BITBLT RPL/RSTR BMONOLEF with pattern\n"); + + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + int16_t x = x_start; + + while (1) { + uint32_t byte_addr = (src_addr >> 3) & mystique->vram_mask; + int bit_offset = src_addr & 7; + + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + ((svga->vram[byte_addr] & (1 << bit_offset)) || !(mystique->dwgreg.dwgctrl_running & DWGCTRL_TRANSC)) && + trans[x & 3]) { + uint32_t src = (svga->vram[byte_addr] & (1 << bit_offset)) ? mystique->dwgreg.fcol : mystique->dwgreg.bcol; + uint32_t dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running);// & DWGCTRL_BOP_MASK + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + default: + fatal("BITBLT RPL BMONOLEF PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; + + if (x != x_end) + x += x_dir; + else + break; + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BU32RGB: + src_addr = mystique->dwgreg.ar[3]; + + for (y = 0; y < mystique->dwgreg.length; y++) { + uint8_t const * const trans = &trans_masks[trans_sel][(mystique->dwgreg.selline & 3) * 4]; + uint32_t old_src_addr = src_addr; + int16_t x = x_start; + + while (1) { + if (x >= mystique->dwgreg.cxleft && x <= mystique->dwgreg.cxright && + mystique->dwgreg.ydst_lin >= mystique->dwgreg.ytop && mystique->dwgreg.ydst_lin <= mystique->dwgreg.ybot && + trans[x & 3]) { + uint32_t src, dst, old_dst; + + switch (mystique->maccess_running & MACCESS_PWIDTH_MASK) { + case MACCESS_PWIDTH_8: + src = svga->vram[src_addr & mystique->vram_mask]; + dst = svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + svga->vram[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_16: + src = ((uint16_t *)svga->vram)[src_addr & mystique->vram_mask_w]; + dst = ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint16_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_w) >> 11] = changeframecount; + break; + + case MACCESS_PWIDTH_24: + src = *(uint32_t *)&svga->vram[(src_addr * 3) & mystique->vram_mask]; + old_dst = *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask]; + + dst = bitop(src, old_dst, mystique->dwgreg.dwgctrl_running); + + *(uint32_t *)&svga->vram[((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask] = (dst & 0xffffff) | (old_dst & 0xff000000); + svga->changedvram[(((mystique->dwgreg.ydst_lin + x) * 3) & mystique->vram_mask) >> 12] = changeframecount; + break; + + case MACCESS_PWIDTH_32: + src = ((uint32_t *)svga->vram)[src_addr & mystique->vram_mask_l]; + dst = ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l]; + + dst = bitop(src, dst, mystique->dwgreg.dwgctrl_running); + + ((uint32_t *)svga->vram)[(mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l] = dst; + svga->changedvram[((mystique->dwgreg.ydst_lin + x) & mystique->vram_mask_l) >> 10] = changeframecount; + break; + + default: + fatal("BITBLT RPL BFCOL PWIDTH %x %08x\n", mystique->maccess_running & MACCESS_PWIDTH_MASK, mystique->dwgreg.dwgctrl_running); + } + } + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) + src_addr = ((src_addr + x_dir) & 7) | (src_addr & ~7); + else if (src_addr == mystique->dwgreg.ar[0]) { + mystique->dwgreg.ar[0] += mystique->dwgreg.ar[5]; + mystique->dwgreg.ar[3] += mystique->dwgreg.ar[5]; + src_addr = mystique->dwgreg.ar[3]; + } else + src_addr += x_dir; + + if (x != x_end) + x += x_dir; + else + break; + } + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_PATTERN) { + src_addr = old_src_addr; + if (mystique->dwgreg.sgn.sdy) + src_addr = ((src_addr - 32) & 0xe0) | (src_addr & ~0xe0); + else + src_addr = ((src_addr + 32) & 0xe0) | (src_addr & ~0xe0); + } + + if (mystique->dwgreg.sgn.sdy) + mystique->dwgreg.ydst_lin -= (mystique->dwgreg.pitch & PITCH_MASK); + else + mystique->dwgreg.ydst_lin += (mystique->dwgreg.pitch & PITCH_MASK); + } + break; + + default: + fatal("BITBLT DWGCTRL_ATYPE_RPL unknown BLTMOD %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + } + break; + + default: + /* pclog("Unknown BITBLT atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); */ + break; + } + + mystique->blitter_complete_refcount++; +} + + +static void +blit_iload(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + case DWGCTRL_ATYPE_RSTR: + case DWGCTRL_ATYPE_BLK: + /* pclog("ILOAD BLTMOD DWGCTRL = %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK); */ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BFCOL: + case DWGCTRL_BLTMOD_BMONOWF: + case DWGCTRL_BLTMOD_BU24RGB: + case DWGCTRL_BLTMOD_BU32RGB: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + /* pclog("ILOAD busy\n"); */ + mystique->dwgreg.words = 0; + break; + + default: + fatal("ILOAD DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static void +blit_idump(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.src_addr = mystique->dwgreg.ar[3]; + mystique->dwgreg.words = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.idump_end_of_line = 0; + mystique->busy = 1; + /* pclog("IDUMP ATYPE RPL busy\n"); */ + break; + + default: + fatal("Unknown IDUMP atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static void +blit_iload_scale(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + /* pclog("ILOAD SCALE ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; + + default: + fatal("ILOAD_SCALE DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_SCALE atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static void +blit_iload_high(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + case DWGCTRL_BLTMOD_BU32BGR: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + /* pclog("ILOAD HIGH ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; + + default: + fatal("ILOAD_HIGH DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGH atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static +void blit_iload_highv(mystique_t *mystique) +{ + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK) { + case DWGCTRL_ATYPE_RPL: + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK) { + case DWGCTRL_BLTMOD_BUYUV: + mystique->dwgreg.length_cur = mystique->dwgreg.length; + mystique->dwgreg.xdst = mystique->dwgreg.fxleft; + mystique->dwgreg.iload_rem_data = 0; + mystique->dwgreg.iload_rem_count = 0; + mystique->busy = 1; + mystique->dwgreg.words = 0; + mystique->dwgreg.highv_line = 0; + mystique->dwgreg.lastpix_r = 0; + mystique->dwgreg.lastpix_g = 0; + mystique->dwgreg.lastpix_b = 0; + /* pclog("ILOAD HIGHV ATYPE RPL BLTMOD BUYUV busy\n"); */ + break; + + default: + fatal("ILOAD_HIGHV DWGCTRL_ATYPE_RPL %08x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_BLTMOD_MASK, mystique->dwgreg.dwgctrl_running); + break; + } + break; + + default: + fatal("Unknown ILOAD_HIGHV atype %03x %08x\n", mystique->dwgreg.dwgctrl_running & DWGCTRL_ATYPE_MASK, mystique->dwgreg.dwgctrl_running); + } +} + + +static void +mystique_start_blit(mystique_t *mystique) +{ + uint64_t start_time = plat_timer_read(); + uint64_t end_time; + + mystique->dwgreg.dwgctrl_running = mystique->dwgreg.dwgctrl; + mystique->maccess_running = mystique->maccess; + + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SOLID) { + int x, y; + + for (y = 0; y < 8; y++) { + for (x = 0; x < 8; x++) + mystique->dwgreg.pattern[y][x] = 1; + } + mystique->dwgreg.src[0] = 0xffffffff; + mystique->dwgreg.src[1] = 0xffffffff; + mystique->dwgreg.src[2] = 0xffffffff; + mystique->dwgreg.src[3] = 0xffffffff; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_ARZERO) { + mystique->dwgreg.ar[0] = 0; + mystique->dwgreg.ar[1] = 0; + mystique->dwgreg.ar[2] = 0; + mystique->dwgreg.ar[4] = 0; + mystique->dwgreg.ar[5] = 0; + mystique->dwgreg.ar[6] = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SGNZERO) { + mystique->dwgreg.sgn.sdydxl = 0; + mystique->dwgreg.sgn.scanleft = 0; + mystique->dwgreg.sgn.sdxl = 0; + mystique->dwgreg.sgn.sdy = 0; + mystique->dwgreg.sgn.sdxr = 0; + } + if (mystique->dwgreg.dwgctrl_running & DWGCTRL_SHTZERO) { + mystique->dwgreg.funcnt = 0; + mystique->dwgreg.stylelen = 0; + mystique->dwgreg.xoff = 0; + mystique->dwgreg.yoff = 0; + } + + switch (mystique->dwgreg.dwgctrl_running & DWGCTRL_OPCODE_MASK) { + case DWGCTRL_OPCODE_LINE_OPEN: + blit_line(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_OPEN: + blit_autoline(mystique, 0); + break; + + case DWGCTRL_OPCODE_AUTOLINE_CLOSE: + blit_autoline(mystique, 1); + break; + + case DWGCTRL_OPCODE_TRAP: + blit_trap(mystique); + break; + + case DWGCTRL_OPCODE_TEXTURE_TRAP: + blit_texture_trap(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGH: + blit_iload_high(mystique); + break; + + case DWGCTRL_OPCODE_BITBLT: + blit_bitblt(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD: + blit_iload(mystique); + break; + + case DWGCTRL_OPCODE_IDUMP: + blit_idump(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_SCALE: + blit_iload_scale(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_HIGHV: + blit_iload_highv(mystique); + break; + + case DWGCTRL_OPCODE_ILOAD_FILTER: + /* TODO: Actually implement this. */ + break; + + default: + fatal("mystique_start_blit: unknown blit %08x\n", mystique->dwgreg.dwgctrl_running); + } + + end_time = plat_timer_read(); + mystique->blitter_time += end_time - start_time; +} + + +static void +mystique_hwcursor_draw(svga_t *svga, int displine) +{ + int x; + uint64_t dat[2]; + int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff; + + if (svga->interlace && svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; + + dat[0] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr]); + dat[1] = *(uint64_t *)(&svga->vram[svga->hwcursor_latch.addr + 8]); + svga->hwcursor_latch.addr += 16; + for (x = 0; x < 64; x ++) { + if (!(dat[1] & (1ull << 63))) + buffer32->line[displine][offset + svga->x_add] = (dat[0] & (1ull << 63)) ? 0xffffff : 0; + else if (dat[0] & (1ull << 63)) + buffer32->line[displine][offset + svga->x_add] ^= 0xffffff; + + offset++; + dat[0] <<= 1; + dat[1] <<= 1; + } + + if (svga->interlace && !svga->hwcursor_oddeven) + svga->hwcursor_latch.addr += 16; +} + + +static +uint8_t mystique_pci_read(int func, int addr, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + uint8_t ret = 0x00; + + if ((addr >= 0x30) && (addr <= 0x33) && !(mystique->pci_regs[0x43] & 0x40)) + ret = 0x00; + else switch (addr) { + case 0x00: ret = 0x2b; break; /*Matrox*/ + case 0x01: ret = 0x10; break; + + case 0x02: ret = 0x1a; break; /*MGA-1064SG*/ + case 0x03: ret = 0x05; break; + + case PCI_REG_COMMAND: + ret = mystique->pci_regs[PCI_REG_COMMAND] | 0x80; break; /*Respond to IO and memory accesses*/ + case 0x05: + ret = 0x00; break; + + case 0x06: ret = 0x80; break; + case 0x07: ret = mystique->pci_regs[0x07]; break; /*Fast DEVSEL timing*/ + + case 0x08: ret = 0; break; /*Revision ID*/ + case 0x09: ret = 0; break; /*Programming interface*/ + + case 0x0a: ret = 0x00; break; /*Supports VGA interface*/ + case 0x0b: ret = 0x03; break; + + case 0x10: ret = 0x00; break; /*Control aperture*/ + case 0x11: ret = (mystique->ctrl_base >> 8) & 0xc0; break; + case 0x12: ret = mystique->ctrl_base >> 16; break; + case 0x13: ret = mystique->ctrl_base >> 24; break; + + case 0x14: ret = 0x00; break; /*Linear frame buffer*/ + case 0x16: ret = (mystique->lfb_base >> 16) & 0x80; break; + case 0x17: ret = mystique->lfb_base >> 24; break; + + case 0x18: ret = 0x00; break; /*Pseudo-DMA (ILOAD)*/ + case 0x1a: ret = (mystique->iload_base >> 16) & 0x80; break; + case 0x1b: ret = mystique->iload_base >> 24; break; + + case 0x2c: ret = mystique->pci_regs[0x2c]; break; + case 0x2d: ret = mystique->pci_regs[0x2d]; break; + case 0x2e: ret = mystique->pci_regs[0x2e]; break; + case 0x2f: ret = mystique->pci_regs[0x2f]; break; + + case 0x30: ret = mystique->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/ + case 0x31: ret = 0x00; break; + case 0x32: ret = mystique->pci_regs[0x32]; break; + case 0x33: ret = mystique->pci_regs[0x33]; break; + + case 0x3c: ret = mystique->int_line; break; + case 0x3d: ret = PCI_INTA; break; + + case 0x40: ret = mystique->pci_regs[0x40]; break; + case 0x41: ret = mystique->pci_regs[0x41]; break; + case 0x42: ret = mystique->pci_regs[0x42]; break; + case 0x43: ret = mystique->pci_regs[0x43]; break; + + case 0x44: ret = mystique->pci_regs[0x44]; break; + case 0x45: ret = mystique->pci_regs[0x45]; break; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + ret = mystique_ctrl_read_b(addr, mystique); break; + } + + return ret; +} + +static void +mystique_pci_write(int func, int addr, uint8_t val, void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + switch (addr) { + case PCI_REG_COMMAND: + mystique->pci_regs[PCI_REG_COMMAND] = (val & 0x27) | 0x80; + mystique_recalc_mapping(mystique); + break; + + case 0x07: + mystique->pci_regs[0x07] &= ~(val & 0x38); + break; + + case 0x0d: + mystique->pci_regs[0x0d] = val; + break; + + case 0x11: + mystique->ctrl_base = (mystique->ctrl_base & 0xffff0000) | ((val & 0xc0) << 8); + mystique_recalc_mapping(mystique); + break; + case 0x12: + mystique->ctrl_base = (mystique->ctrl_base & 0xff00c000) | (val << 16); + mystique_recalc_mapping(mystique); + break; + case 0x13: + mystique->ctrl_base = (mystique->ctrl_base & 0x00ffc000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x16: + mystique->lfb_base = (mystique->lfb_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x17: + mystique->lfb_base = (mystique->lfb_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x1a: + mystique->iload_base = (mystique->iload_base & 0xff000000) | ((val & 0x80) << 16); + mystique_recalc_mapping(mystique); + break; + case 0x1b: + mystique->iload_base = (mystique->iload_base & 0x00800000) | (val << 24); + mystique_recalc_mapping(mystique); + break; + + case 0x30: case 0x32: case 0x33: + if (!(mystique->pci_regs[0x43] & 0x40)) + return; + mystique->pci_regs[addr] = val; + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&mystique->bios_rom.mapping); + return; + + case 0x3c: + mystique->int_line = val; + return; + + case 0x40: + mystique->pci_regs[addr] = val & 0x3f; + break; + case 0x41: + mystique->pci_regs[addr] = val; + break; + case 0x42: + mystique->pci_regs[addr] = val & 0x1f; + break; + case 0x43: + mystique->pci_regs[addr] = val; + if (addr == 0x43) { + if (val & 0x40) { + if (mystique->pci_regs[0x30] & 0x01) { + uint32_t addr = (mystique->pci_regs[0x32] << 16) | (mystique->pci_regs[0x33] << 24); + mem_mapping_set_addr(&mystique->bios_rom.mapping, addr, 0x8000); + } else + mem_mapping_disable(&mystique->bios_rom.mapping); + } else + mem_mapping_set_addr(&mystique->bios_rom.mapping, 0x000c0000, 0x8000); + } + break; + + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + mystique->pci_regs[addr - 0x20] = val; + break; + + case 0x44: + mystique->pci_regs[addr] = val & 0xfc; + break; + case 0x45: + mystique->pci_regs[addr] = val & 0x3f; + break; + + case 0x48: case 0x49: case 0x4a: case 0x4b: + addr = (mystique->pci_regs[0x44] & 0xfc) | ((mystique->pci_regs[0x45] & 0x3f) << 8) | + (addr & 3); + /* pclog("mystique_ctrl_write_b(%04X, %02X)\n", addr, val); */ + mystique_ctrl_write_b(addr, val, mystique); + break; + } +} + + + +static void * +mystique_init(const device_t *info) +{ + int c; + mystique_t *mystique = malloc(sizeof(mystique_t)); + wchar_t *romfn; + + memset(mystique, 0, sizeof(mystique_t)); + + if (info->local == 1) + romfn = ROM_MYSTIQUE_220; + else + romfn = ROM_MYSTIQUE; + + rom_init(&mystique->bios_rom, romfn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + mem_mapping_disable(&mystique->bios_rom.mapping); + + mystique->vram_size = device_get_config_int("memory"); + mystique->vram_mask = (mystique->vram_size << 20) - 1; + mystique->vram_mask_w = mystique->vram_mask >> 1; + mystique->vram_mask_l = mystique->vram_mask >> 2; + + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_matrox_mystique); + + svga_init(&mystique->svga, mystique, mystique->vram_size << 20, + mystique_recalctimings, + mystique_in, mystique_out, + mystique_hwcursor_draw, + NULL); + + io_sethandler(0x03c0, 0x0020, mystique_in, NULL, NULL, mystique_out, NULL, NULL, mystique); + mem_mapping_add(&mystique->ctrl_mapping, 0, 0, + mystique_ctrl_read_b, NULL, mystique_ctrl_read_l, + mystique_ctrl_write_b, NULL, mystique_ctrl_write_l, + NULL, 0, mystique); + mem_mapping_disable(&mystique->ctrl_mapping); + + mem_mapping_add(&mystique->lfb_mapping, 0, 0, + svga_read_linear, svga_readw_linear, svga_readl_linear, + svga_write_linear, svga_writew_linear, svga_writel_linear, + NULL, 0, mystique); + mem_mapping_disable(&mystique->lfb_mapping); + + mem_mapping_add(&mystique->iload_mapping, 0, 0, + mystique_iload_read_b, NULL, mystique_iload_read_l, + mystique_iload_write_b, NULL, mystique_iload_write_l, + NULL, 0, mystique); + mem_mapping_disable(&mystique->iload_mapping); + + mystique->card = pci_add_card(PCI_ADD_VIDEO, mystique_pci_read, mystique_pci_write, mystique); + mystique->pci_regs[0x06] = 0x80; + mystique->pci_regs[0x07] = 0 << 1; + mystique->pci_regs[0x2c] = mystique->bios_rom.rom[0x7ff8]; + mystique->pci_regs[0x2d] = mystique->bios_rom.rom[0x7ff9]; + mystique->pci_regs[0x2e] = mystique->bios_rom.rom[0x7ffa]; + mystique->pci_regs[0x2f] = mystique->bios_rom.rom[0x7ffb]; + + mystique->svga.miscout = 1; + mystique->pci_regs[0x41] = 0x01; /* vgaboot = 1 */ + mystique->pci_regs[0x43] = 0x40; /* biosen = 1 */ + + for (c = 0; c < 256; c++) { + dither5[c][0][0] = c >> 3; + dither5[c][1][1] = (c + 2) >> 3; + dither5[c][1][0] = (c + 4) >> 3; + dither5[c][0][1] = (c + 6) >> 3; + + if (dither5[c][1][1] > 31) + dither5[c][1][1] = 31; + if (dither5[c][1][0] > 31) + dither5[c][1][0] = 31; + if (dither5[c][0][1] > 31) + dither5[c][0][1] = 31; + + dither6[c][0][0] = c >> 2; + dither6[c][1][1] = (c + 1) >> 2; + dither6[c][1][0] = (c + 2) >> 2; + dither6[c][0][1] = (c + 3) >> 2; + + if (dither6[c][1][1] > 63) + dither6[c][1][1] = 63; + if (dither6[c][1][0] > 63) + dither6[c][1][0] = 63; + if (dither6[c][0][1] > 63) + dither6[c][0][1] = 63; + } + + mystique->wake_fifo_thread = thread_create_event(); + mystique->fifo_not_full_event = thread_create_event(); + mystique->fifo_thread = thread_create(fifo_thread, mystique); + mystique->dma.lock = thread_create_mutex(L"86Box.MGAMutex"); + + timer_add(&mystique->wake_timer, mystique_wake_timer, (void *)mystique, 0); + timer_add(&mystique->softrap_pending_timer, mystique_softrap_pending_timer, (void *)mystique, 1); + + mystique->status = STATUS_ENDPRDMASTS; + + return mystique; +} + + +static void +mystique_close(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + thread_kill(mystique->fifo_thread); + thread_destroy_event(mystique->wake_fifo_thread); + thread_destroy_event(mystique->fifo_not_full_event); + thread_close_mutex(mystique->dma.lock); + + svga_close(&mystique->svga); + + free(mystique); +} + + +static int +mystique_available(void) +{ + return rom_present(ROM_MYSTIQUE); +} + + +static int +mystique_220_available(void) +{ + return rom_present(ROM_MYSTIQUE_220); +} + + +static void +mystique_speed_changed(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + svga_recalctimings(&mystique->svga); +} + + +static void +mystique_force_redraw(void *p) +{ + mystique_t *mystique = (mystique_t *)p; + + mystique->svga.fullchange = changeframecount; +} + + +static const device_config_t mystique_config[] = +{ + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .selection = + { + { + .description = "2 MB", + .value = 2 + }, + { + .description = "4 MB", + .value = 4 + }, + { + .description = "8 MB", + .value = 8 + }, + { + .description = "" + } + }, + .default_int = 8 + }, + { + .type = -1 + } +}; + + +const device_t mystique_device = +{ + "Matrox Mystique", + DEVICE_PCI, + 0, + mystique_init, + mystique_close, + NULL, + mystique_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; + + +const device_t mystique_220_device = +{ + "Matrox Mystique 220", + DEVICE_PCI, + 1, + mystique_init, + mystique_close, + NULL, + mystique_220_available, + mystique_speed_changed, + mystique_force_redraw, + mystique_config +}; diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index 467d2a67c..09e56cb10 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -20,14 +20,13 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" -#include "vid_oak_oti.h" #include "vid_svga.h" #define BIOS_037C_PATH L"roms/video/oti/bios.bin" @@ -372,8 +371,10 @@ oti_init(const device_t *info) break; } - rom_init(&oti->bios_rom, romfn, - 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + if (romfn != NULL) { + rom_init(&oti->bios_rom, romfn, + 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } oti->vram_mask = (oti->vram_size << 10) - 1; diff --git a/src/video/vid_oak_oti.h b/src/video/vid_oak_oti.h deleted file mode 100644 index e59d6bcc7..000000000 --- a/src/video/vid_oak_oti.h +++ /dev/null @@ -1,8 +0,0 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -extern const device_t oti037c_device; -extern const device_t oti067_device; -extern const device_t oti067_acer386_device; -extern const device_t oti067_ama932j_device; -extern const device_t oti077_device; diff --git a/src/video/vid_paradise.c b/src/video/vid_paradise.c index 5333980de..ad05e824b 100644 --- a/src/video/vid_paradise.c +++ b/src/video/vid_paradise.c @@ -23,14 +23,13 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" -#include "vid_paradise.h" #include "vid_svga.h" #include "vid_svga_render.h" diff --git a/src/video/vid_paradise.h b/src/video/vid_paradise.h deleted file mode 100644 index bdc4734aa..000000000 --- a/src/video/vid_paradise.h +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright holders: Sarah Walker, Tenshi - see COPYING for more details -*/ -extern const device_t paradise_pvga1a_pc2086_device; -extern const device_t paradise_pvga1a_pc3086_device; -extern const device_t paradise_pvga1a_device; -extern const device_t paradise_wd90c11_megapc_device; -extern const device_t paradise_wd90c11_device; -extern const device_t paradise_wd90c30_device; diff --git a/src/video/vid_pgc.c b/src/video/vid_pgc.c index e8ccbee4b..3db6b4521 100644 --- a/src/video/vid_pgc.c +++ b/src/video/vid_pgc.c @@ -79,14 +79,14 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../pit.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "timer.h" +#include "device.h" +#include "pit.h" +#include "plat.h" #include "video.h" #include "vid_cga.h" #include "vid_pgc.h" @@ -112,7 +112,8 @@ static const char *pgc_err_msgs[] = { "Stack \r", "Too long\r", "Area \r", - "Missing \r" + "Missing \r", + "Unknown \r" }; @@ -862,12 +863,27 @@ pgc_fill_polygon(pgc_t *dev, unsigned corners, int32_t *x, int32_t *y) pgc_log("PGC: fill_polygon(%i corners)\n", corners); - if (corners < 2) return; /* Degenerate polygon */ + if (!x || !y || (corners < 2)) + return; /* Degenerate polygon */ nodex = (double *)malloc(corners * sizeof(double)); dx = (double *)malloc(corners * sizeof(double)); dy = (double *)malloc(corners * sizeof(double)); - if (!nodex || !dx || !dy) return; + if (!nodex || !dx || !dy) { + if (nodex) { + free(nodex); + nodex = NULL; + } + if (dx) { + free(dx); + dx = NULL; + } + if (dy) { + free(dy); + dy = NULL; + } + return; + } ymin = ymax = y[0] / 65536.0; for (n = 0; n < corners; n++) { @@ -1664,7 +1680,6 @@ pgc_wake(pgc_t *dev) void pgc_sleep(pgc_t *dev) { - uint8_t *n = NULL; pgc_log("PGC: sleeping on %i %i %i %i 0x%02x 0x%02x\n", dev->stopped, dev->waiting_input_fifo, dev->waiting_output_fifo, @@ -1674,7 +1689,6 @@ pgc_sleep(pgc_t *dev) if (dev->stopped) { dev->waiting_input_fifo = 0; dev->waiting_output_fifo = 0; - *n = 0; return; } @@ -2019,7 +2033,10 @@ pgc_parse_words(pgc_t *dev, pgc_cl_t *cl, int count) } for (n = 0; n < count; n++) { - if (! pgc_param_word(dev, ¶m[n])) return 0; + if (! pgc_param_word(dev, ¶m[n])) { + free(param); + return 0; + } if (!pgc_cl_append(cl, param[n] & 0xff) || !pgc_cl_append(cl, param[n] >> 8)) { @@ -2047,8 +2064,12 @@ pgc_parse_coords(pgc_t *dev, pgc_cl_t *cl, int count) return 0; } - for (n = 0; n < count; n++) - if (! pgc_param_coord(dev, ¶m[n])) return 0; + for (n = 0; n < count; n++) { + if (! pgc_param_coord(dev, ¶m[n])) { + free(param); + return 0; + } + } /* Here is how the real PGC serializes coords: * diff --git a/src/video/vid_pgc.h b/src/video/vid_pgc.h index 82ef899ea..d1e8c4ffa 100644 --- a/src/video/vid_pgc.h +++ b/src/video/vid_pgc.h @@ -181,7 +181,4 @@ extern void pgc_hndl_lut8(pgc_t *); extern void pgc_hndl_lut8rd(pgc_t *); -extern const device_t pgc_device; - - #endif /*VID_PGC_H*/ diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 7915e5544..60d3a5f4b 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -21,24 +21,18 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "plat.h" #include "video.h" -#include "vid_s3.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_sdac_ramdac.h" -#include "vid_att20c49x_ramdac.h" -#include "vid_bt48x_ramdac.h" -#include "vid_av9194.h" -#include "vid_icd2061.h" -#include "../cpu/cpu.h" +#include "cpu.h" #define ROM_ORCHID_86C911 L"roms/video/s3/BIOS.BIN" #define ROM_METHEUS_86C928 L"roms/video/s3/928.vbi" @@ -1595,7 +1589,6 @@ uint8_t s3_in(uint16_t addr, void *p) void s3_recalctimings(svga_t *svga) { s3_t *s3 = (s3_t *)svga->p; - bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) svga->ramdac; int clk_sel = (svga->miscout >> 2) & 3; svga->hdisp = svga->hdisp_old; @@ -1616,11 +1609,9 @@ void s3_recalctimings(svga_t *svga) else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100; if (!svga->rowoffset) svga->rowoffset = 256; - if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) { - svga->interlace = ramdac->cmd_r2 & 0x08; - if (ramdac->cmd_r3 & 0x08) - svga->hdisp *= 2; /* x2 clock multiplier */ - } else + if (s3->chip == S3_VISION964 || s3->chip == S3_86C928) + bt48x_recalctimings(svga->ramdac, svga); + else svga->interlace = svga->crtc[0x42] & 0x20; if ((((svga->miscout >> 2) & 3) == 3) && (s3->chip != S3_TRIO32) && (s3->chip != S3_TRIO64)) @@ -2076,15 +2067,9 @@ uint8_t s3_accel_in(uint16_t port, void *p) break; temp = s3->accel.pix_trans[1]; if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, 0xffffffff, 0, s3); - else s3_accel_start(16, 1, 0xffffffff, 0, s3); - } + s3_accel_start(16, 1, 0xffffffff, 0, s3); else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100)) - { - if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - else s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); - } + s3_accel_start(2, 1, 0xffffffff, 0xffffffff, s3); return temp; case 0xe14a: case 0xe2ea: if (!s3_cpu_dest(s3)) @@ -3775,6 +3760,9 @@ static const device_config_t s3_config[] = { "4 MB", 4 }, + { + "8 MB", 8 + }, { "" } diff --git a/src/video/vid_s3.h b/src/video/vid_s3.h deleted file mode 100644 index a44d5cc27..000000000 --- a/src/video/vid_s3.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 86Box A hypervisor and IBM PC system emulator that specializes in - * running old operating systems and software designed for IBM - * PC systems and compatibles from 1981 through fairly recent - * system designs based on the PCI bus. - * - * This file is part of the 86Box distribution. - * - * Emulation of the S3 Trio32, S3 Trio64, and S3 Vision864 - * graphics cards. - * - * Version: @(#)vid_s3.h 1.0.4 2019/01/12 - * - * Author: Sarah Walker, - * Miran Grca, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ - -const device_t s3_orchid_86c911_isa_device; -const device_t s3_metheus_premier_86c928_isa_device; -const device_t s3_metheus_premier_86c928_vlb_device; -const device_t s3_v7mirage_86c801_isa_device; -const device_t s3_phoenix_86c805_vlb_device; -const device_t s3_bahamas64_vlb_device; -const device_t s3_bahamas64_pci_device; -const device_t s3_9fx_vlb_device; -const device_t s3_9fx_pci_device; -const device_t s3_phoenix_trio32_vlb_device; -const device_t s3_phoenix_trio32_pci_device; -const device_t s3_phoenix_trio64_vlb_device; -const device_t s3_phoenix_trio64_onboard_pci_device; -const device_t s3_phoenix_trio64_pci_device; -const device_t s3_phoenix_vision864_pci_device; -const device_t s3_phoenix_vision864_vlb_device; -const device_t s3_diamond_stealth64_pci_device; -const device_t s3_diamond_stealth64_vlb_device; -const device_t s3_diamond_stealth64_964_pci_device; -const device_t s3_diamond_stealth64_964_vlb_device; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 1e1bf4dad..358c3c749 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -23,16 +23,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../device.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "device.h" +#include "plat.h" #include "video.h" -#include "vid_s3_virge.h" #include "vid_svga.h" #include "vid_svga_render.h" diff --git a/src/video/vid_s3_virge.h b/src/video/vid_s3_virge.h deleted file mode 100644 index 2d340f649..000000000 --- a/src/video/vid_s3_virge.h +++ /dev/null @@ -1,11 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t s3_virge_vlb_device; -extern const device_t s3_virge_pci_device; -extern const device_t s3_virge_988_vlb_device; -extern const device_t s3_virge_988_pci_device; -extern const device_t s3_virge_375_vlb_device; -extern const device_t s3_virge_375_pci_device; -extern const device_t s3_virge_375_4_vlb_device; -extern const device_t s3_virge_375_4_pci_device; diff --git a/src/video/vid_sc1502x_ramdac.c b/src/video/vid_sc1502x_ramdac.c index 75cb01995..882f892b0 100644 --- a/src/video/vid_sc1502x_ramdac.c +++ b/src/video/vid_sc1502x_ramdac.c @@ -29,12 +29,19 @@ #include "../timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_sc1502x_ramdac.h" + + +typedef struct +{ + int state; + uint8_t ctrl; +} sc1502x_ramdac_t; void -sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga) +sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) { + sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p; int oldbpp = 0; switch (addr) { @@ -102,10 +109,10 @@ sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t uint8_t -sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga) +sc1502x_ramdac_in(uint16_t addr, void *p, svga_t *svga) { - uint8_t temp; - temp = svga_in(addr, svga); + sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) p; + uint8_t temp = svga_in(addr, svga); switch (addr) { case 0x3C6: diff --git a/src/video/vid_sc1502x_ramdac.h b/src/video/vid_sc1502x_ramdac.h deleted file mode 100644 index a5dcd234c..000000000 --- a/src/video/vid_sc1502x_ramdac.h +++ /dev/null @@ -1,30 +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. - * - * Header of the emulation of a Sierra SC1502X RAMDAC. - * - * Used by the TLIVESA1 driver for ET4000. - * - * Version: @(#)vid_sc1502x_ramdac.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct -{ - int state; - uint8_t ctrl; -} sc1502x_ramdac_t; - -extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga); -extern uint8_t sc1502x_ramdac_in(uint16_t addr, sc1502x_ramdac_t *ramdac, svga_t *svga); - -extern const device_t sc1502x_ramdac_device; diff --git a/src/video/vid_sdac_ramdac.c b/src/video/vid_sdac_ramdac.c index 44fb8d752..498daf432 100644 --- a/src/video/vid_sdac_ramdac.c +++ b/src/video/vid_sdac_ramdac.c @@ -21,13 +21,22 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../mem.h" -#include "../timer.h" +#include "86box.h" +#include "device.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_sdac_ramdac.h" + + +typedef struct sdac_ramdac_t +{ + uint16_t regs[256]; + int magic_count, + windex, rindex, + reg_ff, rs2; + uint8_t type, command; +} sdac_ramdac_t; static void @@ -96,8 +105,9 @@ sdac_reg_read(sdac_ramdac_t *ramdac, int reg) void -sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga) +sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga) { + sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; uint8_t rs = (addr & 0x03); rs |= (!!rs2 << 8); @@ -132,8 +142,9 @@ sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, sdac_ramdac_t *ramdac, svga uint8_t -sdac_ramdac_in(uint16_t addr, int rs2, sdac_ramdac_t *ramdac, svga_t *svga) +sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga) { + sdac_ramdac_t *ramdac = (sdac_ramdac_t *) p; uint8_t temp = 0xff; uint8_t rs = (addr & 0x03); rs |= (!!rs2 << 8); diff --git a/src/video/vid_sdac_ramdac.h b/src/video/vid_sdac_ramdac.h deleted file mode 100644 index e57d24519..000000000 --- a/src/video/vid_sdac_ramdac.h +++ /dev/null @@ -1,33 +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. - * - * 87C716 'SDAC' true colour RAMDAC emulation header. - * - * Version: @(#)vid_sdac_ramdac.h 1.0.1 2019/09/13 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - */ -typedef struct sdac_ramdac_t -{ - uint16_t regs[256]; - int magic_count, - windex, rindex, - reg_ff, rs2; - uint8_t type, command; -} sdac_ramdac_t; - -extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga); -extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, sdac_ramdac_t *ramdac, svga_t *svga); -extern float sdac_getclock(int clock, void *p); - -extern const device_t gendac_ramdac_device; -extern const device_t sdac_ramdac_device; diff --git a/src/video/vid_sigma.c b/src/video/vid_sigma.c index 3ad4a2a54..7193783f1 100644 --- a/src/video/vid_sigma.c +++ b/src/video/vid_sigma.c @@ -19,17 +19,16 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../nmi.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "nmi.h" +#include "rom.h" +#include "device.h" #include "video.h" -#include "vid_sigma.h" #define ROM_SIGMA_FONT L"roms/video/sigma/sigma400_font.rom" diff --git a/src/video/vid_sigma.h b/src/video/vid_sigma.h deleted file mode 100644 index e331ad753..000000000 --- a/src/video/vid_sigma.h +++ /dev/null @@ -1,2 +0,0 @@ -extern const device_t sigma_device; - diff --git a/src/video/vid_stg_ramdac.c b/src/video/vid_stg_ramdac.c index 75722ef5a..4900ff5b8 100644 --- a/src/video/vid_stg_ramdac.c +++ b/src/video/vid_stg_ramdac.c @@ -27,7 +27,15 @@ #include "../timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_stg_ramdac.h" + + +typedef struct stg_ramdac_t +{ + int magic_count, index; + uint8_t regs[256]; + uint8_t command; +} stg_ramdac_t; + static int stg_state_read[2][8] = {{1,2,3,4,0,0,0,0}, {1,2,3,4,5,6,7,7}}; @@ -82,8 +90,9 @@ stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac) void -stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga) +stg_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) { + stg_ramdac_t *ramdac = (stg_ramdac_t *) p; int didwrite, old; switch (addr) { @@ -136,8 +145,9 @@ stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga) uint8_t -stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga) +stg_ramdac_in(uint16_t addr, void *p, svga_t *svga) { + stg_ramdac_t *ramdac = (stg_ramdac_t *) p; uint8_t temp = 0xff; switch (addr) { diff --git a/src/video/vid_stg_ramdac.h b/src/video/vid_stg_ramdac.h deleted file mode 100644 index 76dbfcd3e..000000000 --- a/src/video/vid_stg_ramdac.h +++ /dev/null @@ -1,30 +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. - * - * STG1702 true colour RAMDAC emulation header. - * - * Version: @(#)vid_stg_ramdac.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct stg_ramdac_t -{ - int magic_count, index; - uint8_t regs[256]; - uint8_t command; -} stg_ramdac_t; - -extern void stg_ramdac_out(uint16_t addr, uint8_t val, stg_ramdac_t *ramdac, svga_t *svga); -extern uint8_t stg_ramdac_in(uint16_t addr, stg_ramdac_t *ramdac, svga_t *svga); -extern float stg_getclock(int clock, void *p); - -extern const device_t stg_ramdac_device; diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index a07764f12..efceec413 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -11,7 +11,7 @@ * This is intended to be used by another SVGA driver, * and not as a card in it's own right. * - * Version: @(#)vid_svga.c 1.0.40 2019/12/28 + * Version: @(#)vid_svga.c 1.0.42 2020/01/20 * * Authors: Sarah Walker, * Miran Grca, @@ -25,14 +25,14 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../io.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "timer.h" +#include "86box_io.h" +#include "pit.h" +#include "mem.h" +#include "rom.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" @@ -516,6 +516,8 @@ svga_recalctimings(svga_t *svga) svga->linedbl = svga->crtc[9] & 0x80; svga->rowcount = svga->crtc[9] & 31; + svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9; + if (enable_overscan) { overscan_y = (svga->rowcount + 1) << 1; @@ -540,7 +542,7 @@ svga_recalctimings(svga_t *svga) if (svga->vblankstart < svga->dispend) svga->dispend = svga->vblankstart; - crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); + crtcconst = svga->clock * svga->char_width; disptime = svga->htotal; _dispontime = svga->hdisp_time; @@ -563,6 +565,44 @@ svga_recalctimings(svga_t *svga) } +static void +svga_do_render(svga_t *svga) +{ + if (!svga->override) { + svga->render(svga); + + svga->x_add = (overscan_x >> 1); + svga_render_overscan_left(svga); + svga_render_overscan_right(svga); + svga->x_add = (overscan_x >> 1) - svga->scrollcache; + } + + if (svga->overlay_on) { + if (!svga->override && svga->overlay_draw) + svga->overlay_draw(svga, svga->displine + svga->y_add); + svga->overlay_on--; + if (svga->overlay_on && svga->interlace) + svga->overlay_on--; + } + + if (svga->dac_hwcursor_on) { + if (!svga->override && svga->dac_hwcursor_draw) + svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); + svga->dac_hwcursor_on--; + if (svga->dac_hwcursor_on && svga->interlace) + svga->dac_hwcursor_on--; + } + + if (svga->hwcursor_on) { + if (!svga->override && svga->hwcursor_draw) + svga->hwcursor_draw(svga, svga->displine + svga->y_add); + svga->hwcursor_on--; + if (svga->hwcursor_on && svga->interlace) + svga->hwcursor_on--; + } +} + + void svga_poll(void *p) { @@ -570,6 +610,7 @@ svga_poll(void *p) uint32_t x, blink_delay; int wx, wy; int skip = (svga->crtc[8] >> 5) & 0x03; + int ret, old_ma; if (!svga->linepos) { if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { @@ -622,38 +663,24 @@ svga_poll(void *p) svga->interlace ? 3 : 2; } - if (!svga->override) { - svga->render(svga); + if (svga->vertical_linedbl) { + old_ma = svga->ma; - svga->x_add = (overscan_x >> 1); - svga_render_overscan_left(svga); - svga_render_overscan_right(svga); - svga->x_add = (overscan_x >> 1) - svga->scrollcache; - } + svga->displine <<= 1; + svga->y_add <<= 1; - if (svga->overlay_on) { - if (!svga->override && svga->overlay_draw) - svga->overlay_draw(svga, svga->displine + svga->y_add); - svga->overlay_on--; - if (svga->overlay_on && svga->interlace) - svga->overlay_on--; - } + svga_do_render(svga); - if (svga->dac_hwcursor_on) { - if (!svga->override && svga->dac_hwcursor_draw) - svga->dac_hwcursor_draw(svga, svga->displine + svga->y_add); - svga->dac_hwcursor_on--; - if (svga->dac_hwcursor_on && svga->interlace) - svga->dac_hwcursor_on--; - } + svga->displine++; - if (svga->hwcursor_on) { - if (!svga->override && svga->hwcursor_draw) - svga->hwcursor_draw(svga, svga->displine + svga->y_add); - svga->hwcursor_on--; - if (svga->hwcursor_on && svga->interlace) - svga->hwcursor_on--; - } + svga->ma = old_ma; + + svga_do_render(svga); + + svga->y_add >>= 1; + svga->displine >>= 1; + } else + svga_do_render(svga); if (svga->lastline < svga->displine) svga->lastline = svga->displine; @@ -697,15 +724,28 @@ svga_poll(void *p) svga->ma = svga->maback; } } + + svga->hsync_divisor = !svga->hsync_divisor; + + if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) + return; + svga->vc++; svga->vc &= 2047; if (svga->vc == svga->split) { - svga->ma = svga->maback = 0; - svga->sc = 0; - if (svga->attrregs[0x10] & 0x20) { - svga->scrollcache = 0; - svga->x_add = (overscan_x >> 1); + ret = 1; + + if (svga->line_compare) + ret = svga->line_compare(svga); + + if (ret) { + svga->ma = svga->maback = 0; + svga->sc = 0; + if (svga->attrregs[0x10] & 0x20) { + svga->scrollcache = 0; + svga->x_add = (overscan_x >> 1); + } } } if (svga->vc == svga->dispend) { @@ -742,10 +782,16 @@ svga_poll(void *p) svga->firstline--; wx = x; - wy = svga->lastline - svga->firstline; - if (!svga->override/* && (wx > 0) && (wy > 0)*/) - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + if (!svga->override) { + if (svga->vertical_linedbl) { + wy = (svga->lastline - svga->firstline) << 1; + svga_doblit(svga->firstline_draw << 1, (svga->lastline_draw + 1) << 1, wx, wy, svga); + } else { + wy = svga->lastline - svga->firstline; + svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); + } + } svga->firstline = 2000; svga->lastline = 0; @@ -1197,6 +1243,12 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) x_start = (enable_overscan) ? 0 : (overscan_x >> 1); bottom = (overscan_y >> 1) + (svga->crtc[8] & 0x1f); + if (svga->vertical_linedbl) { + y_add <<= 1; + y_start <<= 1; + bottom <<= 1; + } + if ((wx <= 0) || (wy <= 0)) { video_blit_memtoscreen(x_start, y_start, 0, 0, 0, 0); return; @@ -1207,8 +1259,13 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) return; } + if (svga->vertical_linedbl) + svga->y_add <<= 1; + xs_temp = wx; ys_temp = wy + 1; + if (svga->vertical_linedbl) + ys_temp++; if (xs_temp < 64) xs_temp = 640; if (ys_temp < 32) @@ -1252,6 +1309,9 @@ svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) } video_blit_memtoscreen(x_start, y_start, y1, y2 + y_add, xsize + x_add, ysize + y_add); + + if (svga->vertical_linedbl) + svga->vertical_linedbl >>= 1; } diff --git a/src/video/vid_svga.h b/src/video/vid_svga.h index 589039d3d..d2076c2eb 100644 --- a/src/video/vid_svga.h +++ b/src/video/vid_svga.h @@ -8,7 +8,7 @@ * * Generic SVGA handling. * - * Version: @(#)vid_svga.h 1.0.15 2018/10/04 + * Version: @(#)vid_svga.h 1.0.16 2020/01/18 * * Authors: Sarah Walker, * Miran Grca, @@ -53,7 +53,7 @@ typedef struct svga_t hdisp, hdisp_old, htotal, hdisp_time, rowoffset, dispon, hdisp_on, vc, sc, linepos, vslines, linecountff, oddeven, - con, cursoron, blink, scrollcache, + con, cursoron, blink, scrollcache, char_width, firstline, lastline, firstline_draw, lastline_draw, displine, fullchange, x_add, y_add, pan, vram_display_mask, vidclock, @@ -109,6 +109,11 @@ typedef struct svga_t void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr); float (*getclock)(int clock, void *p); + /* Called when VC=R18 and friends. If this returns zero then MA resetting + is skipped. Matrox Mystique in Power mode reuses this counter for + vertical line interrupt*/ + int (*line_compare)(struct svga_t *svga); + /*If set then another device is driving the monitor output and the SVGA card should not attempt to display anything */ int override; @@ -126,6 +131,11 @@ typedef struct svga_t dac_mask, dac_status, ksc5601_sbyte_mask; + int vertical_linedbl; + + /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ + int hsync_divisor; + void *ramdac, *clock_gen; } svga_t; @@ -177,3 +187,69 @@ enum { RAMDAC_6BIT = 0, RAMDAC_8BIT }; + + +/* We need a way to add a device with a pointer to a parent device so it can attach itself to it, and + possibly also a second ATi 68860 RAM DAC type that auto-sets SVGA render on RAM DAC render change. */ +extern void ati68860_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); +extern uint8_t ati68860_ramdac_in(uint16_t addr, void *p, svga_t *svga); +extern void ati68860_set_ramdac_type(void *p, int type); +extern void ati68860_ramdac_set_render(void *p, svga_t *svga); +extern void ati68860_ramdac_set_pallook(void *p, int i, uint32_t col); +extern void ati68860_hwcursor_draw(svga_t *svga, int displine); + +extern void att49x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); +extern uint8_t att49x_ramdac_in(uint16_t addr, void *p, svga_t *svga); + +extern float av9194_getclock(int clock, void *p); + +extern void bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *p, svga_t *svga); +extern uint8_t bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *p, svga_t *svga); +extern void bt48x_recalctimings(void *p, svga_t *svga); +extern void bt48x_hwcursor_draw(svga_t *svga, int displine); + +extern void icd2061_write(void *p, int val); +extern float icd2061_getclock(int clock, void *p); + +/* The code is the same, the #define's are so that the correct name can be used. */ +#define ics9161_write icd2061_write +#define ics9161_getclock icd2061_getclock + +extern void ics2595_write(void *p, int strobe, int dat); +extern double ics2595_getclock(void *p); +extern void ics2595_setclock(void *p, double clock); + +extern void sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); +extern uint8_t sc1502x_ramdac_in(uint16_t addr, void *p, svga_t *svga); + +extern void sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *p, svga_t *svga); +extern uint8_t sdac_ramdac_in(uint16_t addr, int rs2, void *p, svga_t *svga); +extern float sdac_getclock(int clock, void *p); + +extern void stg_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); +extern uint8_t stg_ramdac_in(uint16_t addr, void *p, svga_t *svga); +extern float stg_getclock(int clock, void *p); + +extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga); +extern uint8_t tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga); + + +#ifdef EMU_DEVICE_H +extern const device_t ati68860_ramdac_device; +extern const device_t att490_ramdac_device; +extern const device_t att492_ramdac_device; +extern const device_t av9194_device; +extern const device_t bt484_ramdac_device; +extern const device_t att20c504_ramdac_device; +extern const device_t bt485_ramdac_device; +extern const device_t att20c505_ramdac_device; +extern const device_t bt485a_ramdac_device; +extern const device_t gendac_ramdac_device; +extern const device_t ics2595_device; +extern const device_t icd2061_device; +extern const device_t ics9161_device; +extern const device_t sc1502x_ramdac_device; +extern const device_t sdac_ramdac_device; +extern const device_t stg_ramdac_device; +extern const device_t tkd8001_ramdac_device; +#endif diff --git a/src/video/vid_svga_render.c b/src/video/vid_svga_render.c index 2448bd1fb..499c02f91 100644 --- a/src/video/vid_svga_render.c +++ b/src/video/vid_svga_render.c @@ -20,9 +20,9 @@ #include #include #include -#include "../86box.h" -#include "../mem.h" -#include "../timer.h" +#include "86box.h" +#include "mem.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" diff --git a/src/video/vid_table.c b/src/video/vid_table.c index d86e61686..e5db46fd0 100644 --- a/src/video/vid_table.c +++ b/src/video/vid_table.c @@ -8,13 +8,13 @@ * * Define all known video cards. * - * Version: @(#)vid_table.c 1.0.44 2019/10/01 + * Version: @(#)vid_table.c 1.0.49 2020/01/22 * * Authors: Miran Grca, * Fred N. van Kempen, * - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. */ #include #include @@ -23,44 +23,19 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../machine/machine.h" -#include "../mem.h" -#include "../device.h" -#include "../plat.h" +#include "86box.h" +#include "timer.h" +#include "machine.h" +#include "mem.h" +#include "device.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" -#include "vid_ati18800.h" -#include "vid_ati28800.h" -#include "vid_ati_mach64.h" #include "vid_cga.h" -#include "vid_cl54xx.h" -#include "vid_compaq_cga.h" #include "vid_ega.h" -#include "vid_et4000.h" -#include "vid_et4000w32.h" -#include "vid_genius.h" -#include "vid_hercules.h" -#include "vid_herculesplus.h" -#include "vid_ht216.h" -#include "vid_im1024.h" -#include "vid_incolor.h" #include "vid_colorplus.h" #include "vid_mda.h" -#include "vid_oak_oti.h" -#include "vid_paradise.h" -#include "vid_pgc.h" -#include "vid_s3.h" -#include "vid_s3_virge.h" -#include "vid_sigma.h" -#include "vid_tgui9440.h" -#include "vid_ti_cf62011.h" -#include "vid_tvga.h" -#include "vid_vga.h" -#include "vid_voodoo.h" -#include "vid_wy700.h" typedef struct { @@ -79,6 +54,7 @@ static const VIDEO_CARD video_cards[] = { { "None", "none", NULL }, { "Internal", "internal", NULL }, + { "[ISA] ATI EGA Wonder 800+", "egawonder800", &atiega_device }, { "[ISA] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_isa", &mach64gx_isa_device }, { "[ISA] ATI Korean VGA (ATI-28800-5)", "ati28800k", &ati28800k_device }, { "[ISA] ATI VGA-88 (ATI-18800-1)", "ati18800v", &ati18800_vga88_device }, @@ -92,9 +68,9 @@ video_cards[] = { #endif { "[ISA] CGA", "cga", &cga_device }, { "[ISA] Chips & Technologies SuperEGA", "superega", &sega_device }, -#if defined(DEV_BRANCH) && defined(USE_CL5422) { "[ISA] Cirrus Logic CL-GD 5402", "cl_gd5402_isa", &gd5402_isa_device }, { "[ISA] Cirrus Logic CL-GD 5420", "cl_gd5420_isa", &gd5420_isa_device }, +#if defined(DEV_BRANCH) && defined(USE_CL5422) { "[ISA] Cirrus Logic CL-GD 5422", "cl_gd5422_isa", &gd5422_isa_device }, #endif { "[ISA] Cirrus Logic CL-GD 5428", "cl_gd5428_isa", &gd5428_isa_device }, @@ -133,6 +109,7 @@ video_cards[] = { { "[ISA] VGA", "vga", &vga_device }, { "[ISA] Video 7 VGA 1024i", "v7_vga_1024i", &v7_vga_1024i_device }, { "[ISA] Wyse 700", "wy700", &wy700_device }, + { "[MCA] IBM 1MB SVGA Adapter/A (CL-GD 5428)", "ibm1mbsvga", &gd5428_mca_device }, { "[MCA] Tseng ET4000AX", "et4000mca", &et4000_mca_device }, { "[PCI] ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx_pci", &mach64gx_pci_device }, { "[PCI] ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device }, @@ -148,6 +125,8 @@ video_cards[] = { { "[PCI] Diamond Stealth 3D 3000 (S3 ViRGE/VX)", "stealth3d_3000_pci", &s3_virge_988_pci_device }, { "[PCI] Diamond Stealth 64 DRAM (S3 Trio64)", "stealth64d_pci", &s3_diamond_stealth64_pci_device }, { "[PCI] Diamond Stealth 64 VRAM (S3 Vision964)", "stealth64v_pci", &s3_diamond_stealth64_964_pci_device }, + { "[PCI] Matrox Mystique", "mystique", &mystique_device }, + { "[PCI] Matrox Mystique 220", "mystique_220", &mystique_220_device }, { "[PCI] Number Nine 9FX (S3 Trio64)", "n9_9fx_pci", &s3_9fx_pci_device }, { "[PCI] Paradise Bahamas 64 (S3 Vision864)", "bahamas64_pci", &s3_bahamas64_pci_device }, { "[PCI] Phoenix S3 Vision864", "px_vision864_pci", &s3_phoenix_vision864_pci_device }, diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index c366fae12..3290d25cf 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -60,20 +60,18 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../device.h" -#include "../cpu/cpu.h" -#include "../plat.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "device.h" +#include "cpu.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_tkd8001_ramdac.h" -#include "vid_tgui9440.h" /*TGUI9400CXi has extended write modes, controlled by extended GDC registers : @@ -308,6 +306,7 @@ void tgui_out(uint16_t addr, uint8_t val, void *p) } return; } + /*FALLTHROUGH*/ case 0x3C7: case 0x3C8: case 0x3C9: if (tgui->type == TGUI_9400CXI) { diff --git a/src/video/vid_tgui9440.h b/src/video/vid_tgui9440.h deleted file mode 100644 index 24208e913..000000000 --- a/src/video/vid_tgui9440.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t tgui9400cxi_device; -extern const device_t tgui9440_vlb_device; -extern const device_t tgui9440_pci_device; diff --git a/src/video/vid_ti_cf62011.c b/src/video/vid_ti_cf62011.c index e77ce27c9..dde469ba7 100644 --- a/src/video/vid_ti_cf62011.c +++ b/src/video/vid_ti_cf62011.c @@ -57,16 +57,14 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../video/video.h" -#include "../video/vid_vga.h" -#include "../video/vid_svga.h" -#include "vid_ti_cf62011.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "video.h" +#include "vid_svga.h" typedef struct { diff --git a/src/video/vid_ti_cf62011.h b/src/video/vid_ti_cf62011.h deleted file mode 100644 index 185f98511..000000000 --- a/src/video/vid_ti_cf62011.h +++ /dev/null @@ -1,4 +0,0 @@ -#if defined(DEV_BRANCH) && defined(USE_TI) -extern const device_t ti_cf62011_device; -#endif -extern const device_t ibm_ps1_2121_device; diff --git a/src/video/vid_tkd8001_ramdac.c b/src/video/vid_tkd8001_ramdac.c index e7c381a79..26118f1a4 100644 --- a/src/video/vid_tkd8001_ramdac.c +++ b/src/video/vid_tkd8001_ramdac.c @@ -21,18 +21,26 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../timer.h" -#include "../mem.h" +#include "86box.h" +#include "device.h" +#include "timer.h" +#include "mem.h" #include "video.h" #include "vid_svga.h" -#include "vid_tkd8001_ramdac.h" + + +typedef struct tkd8001_ramdac_t +{ + int state; + uint8_t ctrl; +} tkd8001_ramdac_t; void -tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga) +tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *p, svga_t *svga) { + tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p; + switch (addr) { case 0x3C6: if (ramdac->state == 4) { @@ -70,8 +78,10 @@ tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t uint8_t -tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga) +tkd8001_ramdac_in(uint16_t addr, void *p, svga_t *svga) { + tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) p; + switch (addr) { case 0x3C6: if (ramdac->state == 4) diff --git a/src/video/vid_tkd8001_ramdac.h b/src/video/vid_tkd8001_ramdac.h deleted file mode 100644 index 3cfa166b0..000000000 --- a/src/video/vid_tkd8001_ramdac.h +++ /dev/null @@ -1,28 +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. - * - * Trident TKD8001 RAMDAC emulation header. - * - * Version: @(#)vid_tkd8001_ramdac.h 1.0.0 2018/10/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -typedef struct tkd8001_ramdac_t -{ - int state; - uint8_t ctrl; -} tkd8001_ramdac_t; - -extern void tkd8001_ramdac_out(uint16_t addr, uint8_t val, tkd8001_ramdac_t *ramdac, svga_t *svga); -extern uint8_t tkd8001_ramdac_in(uint16_t addr, tkd8001_ramdac_t *ramdac, svga_t *svga); - -extern const device_t tkd8001_ramdac_device; diff --git a/src/video/vid_tvga.c b/src/video/vid_tvga.c index 8e2fd3bc3..301e03816 100644 --- a/src/video/vid_tvga.c +++ b/src/video/vid_tvga.c @@ -21,17 +21,15 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "mem.h" +#include "rom.h" +#include "device.h" #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" -#include "vid_tkd8001_ramdac.h" -#include "vid_tvga.h" #define TVGA8900B_ID 0x03 #define TVGA8900CLD_ID 0x33 diff --git a/src/video/vid_tvga.h b/src/video/vid_tvga.h deleted file mode 100644 index 6a4f0105a..000000000 --- a/src/video/vid_tvga.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t tvga8900b_device; -extern const device_t tvga8900d_device; diff --git a/src/video/vid_vga.c b/src/video/vid_vga.c index b01e9fa53..e38afa6d7 100644 --- a/src/video/vid_vga.c +++ b/src/video/vid_vga.c @@ -21,15 +21,14 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" +#include "86box.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" #include "video.h" #include "vid_svga.h" -#include "vid_vga.h" typedef struct vga_t diff --git a/src/video/vid_vga.h b/src/video/vid_vga.h deleted file mode 100644 index 533fdbb9a..000000000 --- a/src/video/vid_vga.h +++ /dev/null @@ -1,6 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -extern const device_t vga_device; -extern const device_t ps1vga_device; -extern const device_t ps1vga_mca_device; diff --git a/src/video/vid_voodoo.c b/src/video/vid_voodoo.c index 2685aa2ac..e3c0d91a6 100644 --- a/src/video/vid_voodoo.c +++ b/src/video/vid_voodoo.c @@ -22,19 +22,18 @@ #include #include #include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../device.h" -#include "../mem.h" -#include "../pci.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../plat.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "device.h" +#include "mem.h" +#include "pci.h" +#include "rom.h" +#include "timer.h" +#include "device.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" -#include "vid_voodoo.h" #include "vid_voodoo_dither.h" #ifdef CLAMP @@ -5750,7 +5749,7 @@ static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) colour_data[0].b = val & 0xff; colour_data[0].g = (val >> 8) & 0xff; colour_data[0].r = (val >> 16) & 0xff; - alpha_data[0] = (val >> 24) & 0xff; + colour_data[0].a = alpha_data[0] = (val >> 24) & 0xff; write_mask = LFB_WRITE_COLOUR; addr >>= 1; break; diff --git a/src/video/vid_voodoo.h b/src/video/vid_voodoo.h deleted file mode 100644 index 9752899f7..000000000 --- a/src/video/vid_voodoo.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t voodoo_device; diff --git a/src/video/vid_wy700.c b/src/video/vid_wy700.c index b490dc4a6..00fb1b822 100644 --- a/src/video/vid_wy700.c +++ b/src/video/vid_wy700.c @@ -21,14 +21,13 @@ #include #include #include -#include "../86box.h" -#include "../io.h" -#include "../timer.h" -#include "../pit.h" -#include "../mem.h" -#include "../device.h" +#include "86box.h" +#include "86box_io.h" +#include "timer.h" +#include "pit.h" +#include "mem.h" +#include "device.h" #include "video.h" -#include "vid_wy700.h" #define WY700_XSIZE 1280 diff --git a/src/video/vid_wy700.h b/src/video/vid_wy700.h deleted file mode 100644 index 0c8a986fe..000000000 --- a/src/video/vid_wy700.h +++ /dev/null @@ -1 +0,0 @@ -extern const device_t wy700_device; diff --git a/src/video/video.c b/src/video/video.c index 7d87c5382..d3ed0794b 100644 --- a/src/video/video.c +++ b/src/video/video.c @@ -58,14 +58,14 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../config.h" -#include "../timer.h" -#include "../plat.h" +#include "86box.h" +#include "cpu.h" +#include "86box_io.h" +#include "mem.h" +#include "rom.h" +#include "config.h" +#include "timer.h" +#include "plat.h" #include "video.h" #include "vid_svga.h" @@ -776,9 +776,11 @@ set_palette(PALETTE p) void destroy_bitmap(bitmap_t *b) { - if (b->dat != NULL) + if ((b != NULL) && (b->dat != NULL)) free(b->dat); - free(b); + + if (b != NULL) + free(b); } @@ -910,7 +912,7 @@ void loadfont(wchar_t *s, int format) { FILE *f; - int c,d; + int c, d; f = rom_fopen(s, L"rb"); if (f == NULL) @@ -920,24 +922,28 @@ loadfont(wchar_t *s, int format) case 0: /* MDA */ for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); + fontdatm[c][d] = fgetc(f) & 0xff; for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); + fontdatm[c][d+8] = fgetc(f) & 0xff; (void)fseek(f, 4096+2048, SEEK_SET); for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 1: /* PC200 */ for (d = 0; d < 4; d++) { /* There are 4 fonts in the ROM */ - for (c = 0; c < 256; c++) /* 8x14 MDA in 8x16 cell */ - fread(&fontdatm[256*d + c][0], 1, 16, f); + for (c = 0; c < 256; c++) { /* 8x14 MDA in 8x16 cell */ + if (fread(&fontdatm[256*d + c][0], 1, 16, f) != 16) + fatal("loadfont(): Error reading 8x16 font in PC200 mode, c = %i\n", c); + } for (c = 0; c < 256; c++) { /* 8x8 CGA in 8x16 cell */ - fread(&fontdat[256*d + c][0], 1, 8, f); - fseek(f, 8, SEEK_CUR); + if (fread(&fontdat[256*d + c][0], 1, 8, f) != 8) + fatal("loadfont(): Error reading 8x8 font in PC200 mode, c = %i\n", c); + if (fseek(f, 8, SEEK_CUR) == -1) + fatal("loadfont(): Error seeking in PC200 mode, c = %i\n", c); } } break; @@ -946,19 +952,19 @@ loadfont(wchar_t *s, int format) case 2: /* CGA */ for (c=0; c<256; c++) for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 3: /* Wyse 700 */ for (c=0; c<512; c++) for (d=0; d<32; d++) - fontdatw[c][d] = fgetc(f); + fontdatw[c][d] = fgetc(f) & 0xff; break; case 4: /* MDSI Genius */ for (c=0; c<256; c++) for (d=0; d<16; d++) - fontdat8x12[c][d] = fgetc(f); + fontdat8x12[c][d] = fgetc(f) & 0xff; break; case 5: /* Toshiba 3100e */ @@ -1002,7 +1008,7 @@ loadfont(wchar_t *s, int format) for (c = 0; c < 16384; c++) { for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d]=getc(f); + fontdatksc5601[c].chr[d]=fgetc(f) & 0xff; } break; @@ -1013,14 +1019,16 @@ loadfont(wchar_t *s, int format) fseek(f, 8, SEEK_CUR); } /* The second 4k holds an 8x16 font */ - for (c = 0; c < 256; c++) - fread(&fontdatm[c][0], 1, 16, f); + for (c = 0; c < 256; c++) { + if (fread(&fontdatm[c][0], 1, 16, f) != 16) + fatal("loadfont(): Error reading 8x16 font in Sigma Color 400 mode, c = %i\n", c); + } break; case 8: /* Amstrad PC1512, Toshiba T1000/T1200 */ for (c = 0; c < 2048; c++) /* Allow up to 2048 chars */ for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); + fontdat[c][d] = fgetc(f) & 0xff; break; case 9: /* Image Manager 1024 native font */ diff --git a/src/video/video.h b/src/video/video.h index 427b0e5c9..fad5359d4 100644 --- a/src/video/video.h +++ b/src/video/video.h @@ -65,7 +65,7 @@ typedef struct { typedef struct { int w, h; uint32_t *dat; - uint32_t *line[2048]; + uint32_t *line[2112]; } bitmap_t; typedef struct { @@ -190,4 +190,165 @@ extern uint32_t video_color_transform(uint32_t color); #endif +#ifdef EMU_DEVICE_H +/* ATi Mach64 */ +extern const device_t mach64gx_isa_device; +extern const device_t mach64gx_vlb_device; +extern const device_t mach64gx_pci_device; +extern const device_t mach64vt2_device; + +/* ATi 18800 */ +extern const device_t ati18800_wonder_device; +extern const device_t ati18800_vga88_device; +extern const device_t ati18800_device; + +/* ATi 28800 */ +extern const device_t ati28800_device; +extern const device_t ati28800k_device; +extern const device_t compaq_ati28800_device; +#if defined(DEV_BRANCH) && defined(USE_XL24) +extern const device_t ati28800_wonderxl24_device; +#endif + +/* Cirrus Logic CL-GD 54xx */ +extern const device_t gd5402_isa_device; +extern const device_t gd5402_onboard_device; +extern const device_t gd5420_isa_device; +#if defined(DEV_BRANCH) && defined(USE_CL5422) +extern const device_t gd5422_isa_device; +extern const device_t gd5424_vlb_device; +#endif +extern const device_t gd5426_vlb_device; +extern const device_t gd5428_isa_device; +extern const device_t gd5428_vlb_device; +extern const device_t gd5428_mca_device; +extern const device_t gd5429_isa_device; +extern const device_t gd5429_vlb_device; +extern const device_t gd5430_vlb_device; +extern const device_t gd5430_pci_device; +extern const device_t gd5434_isa_device; +extern const device_t gd5434_vlb_device; +extern const device_t gd5434_pci_device; +extern const device_t gd5436_pci_device; +extern const device_t gd5440_onboard_pci_device; +extern const device_t gd5440_pci_device; +extern const device_t gd5446_pci_device; +extern const device_t gd5446_stb_pci_device; +extern const device_t gd5480_pci_device; + +/* Compaq CGA */ +extern const device_t compaq_cga_device; +extern const device_t compaq_cga_2_device; + +/* Tseng ET4000AX */ +extern const device_t et4000_isa_device; +extern const device_t et4000k_isa_device; +extern const device_t et4000k_tg286_isa_device; +extern const device_t et4000_mca_device; + +/* Tseng ET4000-W32p */ +extern const device_t et4000w32p_vlb_device; +extern const device_t et4000w32p_pci_device; +extern const device_t et4000w32p_cardex_vlb_device; +extern const device_t et4000w32p_cardex_pci_device; + +/* MDSI Genius VHR */ +extern const device_t genius_device; + +/* Hercules */ +extern const device_t hercules_device; +extern const device_t herculesplus_device; +extern const device_t incolor_device; + +/* Headland GC-2xx/HT-2xx */ +extern const device_t g2_gc205_device; +extern const device_t v7_vga_1024i_device; +extern const device_t ht216_32_pb410a_device; + +/* Professional Graphics Controller */ +extern const device_t im1024_device; +extern const device_t pgc_device; + +/* Matrox Mystique */ +extern const device_t mystique_device; +extern const device_t mystique_220_device; + +/* Oak OTI-0x7 */ +extern const device_t oti037c_device; +extern const device_t oti067_device; +extern const device_t oti067_acer386_device; +extern const device_t oti067_ama932j_device; +extern const device_t oti077_device; + +/* Paradise/WD (S)VGA */ +extern const device_t paradise_pvga1a_pc2086_device; +extern const device_t paradise_pvga1a_pc3086_device; +extern const device_t paradise_pvga1a_device; +extern const device_t paradise_wd90c11_megapc_device; +extern const device_t paradise_wd90c11_device; +extern const device_t paradise_wd90c30_device; + +/* S3 9XX/8XX/Vision/Trio */ +const device_t s3_orchid_86c911_isa_device; +const device_t s3_metheus_premier_86c928_isa_device; +const device_t s3_metheus_premier_86c928_vlb_device; +const device_t s3_v7mirage_86c801_isa_device; +const device_t s3_phoenix_86c805_vlb_device; +const device_t s3_bahamas64_vlb_device; +const device_t s3_bahamas64_pci_device; +const device_t s3_9fx_vlb_device; +const device_t s3_9fx_pci_device; +const device_t s3_phoenix_trio32_vlb_device; +const device_t s3_phoenix_trio32_pci_device; +const device_t s3_phoenix_trio64_vlb_device; +const device_t s3_phoenix_trio64_onboard_pci_device; +const device_t s3_phoenix_trio64_pci_device; +const device_t s3_phoenix_vision864_pci_device; +const device_t s3_phoenix_vision864_vlb_device; +const device_t s3_diamond_stealth64_pci_device; +const device_t s3_diamond_stealth64_vlb_device; +const device_t s3_diamond_stealth64_964_pci_device; +const device_t s3_diamond_stealth64_964_vlb_device; + +/* S3 ViRGE */ +extern const device_t s3_virge_vlb_device; +extern const device_t s3_virge_pci_device; +extern const device_t s3_virge_988_vlb_device; +extern const device_t s3_virge_988_pci_device; +extern const device_t s3_virge_375_vlb_device; +extern const device_t s3_virge_375_pci_device; +extern const device_t s3_virge_375_4_vlb_device; +extern const device_t s3_virge_375_4_pci_device; + +/* Sigma Color 400 */ +extern const device_t sigma_device; + +/* Trident TGUI 94x0 */ +extern const device_t tgui9400cxi_device; +extern const device_t tgui9440_vlb_device; +extern const device_t tgui9440_pci_device; + +/* IBM PS/1 (S)VGA */ +#if defined(DEV_BRANCH) && defined(USE_TI) +extern const device_t ti_cf62011_device; +#endif +extern const device_t ibm_ps1_2121_device; + +/* Trident TVGA 8900 */ +extern const device_t tvga8900b_device; +extern const device_t tvga8900d_device; + +/* IBM VGA */ +extern const device_t vga_device; +extern const device_t ps1vga_device; +extern const device_t ps1vga_mca_device; + +/* 3DFX Voodoo Graphics */ +extern const device_t voodoo_device; + +/* Wyse 700 */ +extern const device_t wy700_device; +#endif + + #endif /*EMU_VIDEO_H*/ diff --git a/src/vnc.c b/src/vnc.c index 7b6040c4b..143b60964 100644 --- a/src/vnc.c +++ b/src/vnc.c @@ -25,7 +25,7 @@ #define HAVE_STDARG_H #include "86box.h" #include "device.h" -#include "video/video.h" +#include "video.h" #include "keyboard.h" #include "mouse.h" #include "plat.h" diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 851b7d287..fe204a04b 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -474,6 +474,9 @@ BEGIN CONTROL "ISABugger device",IDC_CHECK_BUGGER,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,7,80,94,10 + CONTROL "POST card",IDC_CHECK_POSTCARD,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,147,80,94,10 + LTEXT "ISA RTC",IDT_1767,7,99,48,10 COMBOBOX IDC_COMBO_ISARTC,64,98,155,120, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index 901ac9215..bcc10bbd2 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 +# Version: @(#)Makefile.mingw 1.0.143 2020/01/25 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -83,8 +83,11 @@ ifeq ($(DEV_BUILD), y) ifndef VECTRA54 VECTRA54 := y endif - ifndef MICRONICS386 - MICRONICS386 := y + ifndef VPP60 + VP660 := y + endif + ifndef SIEMENS + SIEMENS := y endif ifndef VGAWONDER VGAWONDER := y @@ -147,8 +150,11 @@ else ifndef VECTRA54 VECTRA54 := n endif - ifndef MICRONICS386 - MICRONICS386 := n + ifndef VPP60 + VP660 := n + endif + ifndef SIEMENS + SIEMENS := n endif ifndef VGAWONDER VGAWONDER := n @@ -260,7 +266,7 @@ endif ######################################################################### # Nothing should need changing from here on.. # ######################################################################### -VPATH := $(EXPATH) . cpu \ +VPATH := $(EXPATH) . cpu cpu_common \ cdrom chipset disk floppy game machine \ printer \ sound \ @@ -294,6 +300,17 @@ DEPFILE := win/.depends # Set up the correct toolchain flags. OPTS := $(EXTRAS) $(STUFF) +ifeq ($(WX), y) +OPTS += -I. \ + -Icpu -Icpu_common \ + -Icdrom -Ichipset -Idisk -Ifloppy -Igame -Imachine -Inetwork \ + -Iprinter -Isound -Iscsi -Ivideo -Ilang +else +OPTS += -iquote . \ + -iquote cpu -iquote cpu_common \ + -iquote cdrom -iquote chipset -iquote disk -iquote floppy -iquote game -iquote machine -iquote network \ + -iquote printer -iquote sound -iquote scsi -iquote video -iquote lang +endif ifdef EXFLAGS OPTS += $(EXFLAGS) endif @@ -332,7 +349,7 @@ else endif endif endif -AFLAGS := -msse2 -mfpmath=sse +AFLAGS := -msse2 -mfpmath=387 ifeq ($(ARM), y) DFLAGS := -march=armv7-a AOPTIM := @@ -461,7 +478,6 @@ endif ifeq ($(I686), y) OPTS += -DUSE_I686 -DEVBROBJ += m_at_socket8.o endif ifeq ($(LASERXT), y) @@ -506,8 +522,12 @@ ifeq ($(VECTRA54), y) OPTS += -DUSE_VECTRA54 endif -ifeq ($(MICRONICS386), y) -OPTS += -DUSE_MICRONICS386 +ifeq ($(VPP60), y) +OPTS += -DUSE_VPP60 +endif + +ifeq ($(SIEMENS), y) +OPTS += -DUSE_SIEMENS endif ifeq ($(VGAWONDER), y) @@ -529,8 +549,9 @@ endif # Final versions of the toolchain flags. CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ - $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing -funroll-loops + $(AFLAGS) -pipe -fomit-frame-pointer -mstackrealign -Wall \ + -fno-strict-aliasing +# -funroll-loops # Add freetyp2 references through pkgconfig CFLAGS := $(CFLAGS) `pkg-config.exe --cflags freetype2` @@ -543,21 +564,22 @@ CXXFLAGS := $(CFLAGS) ######################################################################### MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ - rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) + rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ) INTELOBJ := intel_flash.o \ intel_sio.o intel_piix.o CPUOBJ := cpu.o cpu_table.o \ - 808x.o 386.o \ + 808x.o \ + 386.o 386_common.o \ 386_dynarec.o \ x86seg.o x87.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \ - intel_4x0.o neat.o opti495.o scat.o \ + intel_4x0.o neat.o opti495.o scamp.o scat.o \ sis_85c471.o sis_85c496.o \ - wd76c10.o + via_mvp3.o wd76c10.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ @@ -572,14 +594,18 @@ MCHOBJ := machine.o machine_table.o \ m_ps2_isa.o m_ps2_mca.o \ m_at_compaq.o \ m_at_286_386sx.o m_at_386dx_486.o \ - m_at_socket4_5.o m_at_socket7_s7.o + m_at_socket4_5.o m_at_socket7_s7.o \ + m_at_socket8.o -DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_w83781d.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ sio_acc3221.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \ - sio_pc87306.o sio_w83877f.o \ + sio_pc87306.o \ + sio_w83787f.o \ + sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \ + smbus.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ gameport.o \ @@ -616,7 +642,8 @@ SCSIOBJ := scsi.o scsi_device.o \ scsi_cdrom.o scsi_disk.o \ scsi_x54x.o \ scsi_aha154x.o scsi_buslogic.o \ - scsi_ncr5380.o scsi_ncr53c8xx.o + scsi_ncr5380.o scsi_ncr53c8xx.o \ + scsi_spock.o NETOBJ := network.o \ net_pcap.o \ @@ -678,6 +705,7 @@ VIDOBJ := video.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ vid_ht216.o \ + vid_mga.o \ vid_oak_oti.o \ vid_paradise.o \ vid_ti_cf62011.o \ @@ -777,7 +805,7 @@ all: $(PROG).exe pcap_if.exe $(PROG).exe: $(OBJ) 86Box.res @echo Linking $(PROG).exe .. - @$(CC) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) + @$(CC) -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) -pipe ifneq ($(DEBUG), y) @$(STRIP) $(PROG).exe endif diff --git a/src/win/Makefile_ndr.mingw b/src/win/Makefile_ndr.mingw index facc55327..23466a8f6 100644 --- a/src/win/Makefile_ndr.mingw +++ b/src/win/Makefile_ndr.mingw @@ -8,7 +8,7 @@ # # Makefile for Win32 (MinGW32) environment. # -# Version: @(#)Makefile.mingw 1.0.140 2019/12/21 +# Version: @(#)Makefile.mingw 1.0.142 2020/01/25 # # Authors: Miran Grca, # Fred N. van Kempen, @@ -83,8 +83,11 @@ ifeq ($(DEV_BUILD), y) ifndef VECTRA54 VECTRA54 := y endif - ifndef MICRONICS386 - MICRONICS386 := y + ifndef VPP60 + VPP60 := y + endif + ifndef SIEMENS + SIEMENS := y endif ifndef VGAWONDER VGAWONDER := y @@ -147,8 +150,11 @@ else ifndef VECTRA54 VECTRA54 := n endif - ifndef MICRONICS386 - MICRONICS386 := n + ifndef VPP60 + VPP60 := n + endif + ifndef SIEMENS + SIEMENS := n endif ifndef VGAWONDER VGAWONDER := n @@ -260,7 +266,7 @@ endif ######################################################################### # Nothing should need changing from here on.. # ######################################################################### -VPATH := $(EXPATH) . cpu_new \ +VPATH := $(EXPATH) . cpu_new cpu_common \ cdrom chipset disk floppy game machine \ printer \ sound \ @@ -294,6 +300,17 @@ DEPFILE := win/.depends # Set up the correct toolchain flags. OPTS := $(EXTRAS) $(STUFF) +ifeq ($(WX), y) +OPTS += -I. \ + -Icpu_new -Icpu_common \ + -Icdrom -Ichipset -Idisk -Ifloppy -Igame -Imachine -Inetwork \ + -Iprinter -Isound -Iscsi -Ivideo -Ilang +else +OPTS += -iquote . \ + -iquote cpu_new -iquote cpu_common \ + -iquote cdrom -iquote chipset -iquote disk -iquote floppy -iquote game -iquote machine -iquote network \ + -iquote printer -iquote sound -iquote scsi -iquote video -iquote lang +endif ifdef EXFLAGS OPTS += $(EXFLAGS) endif @@ -467,7 +484,6 @@ endif ifeq ($(I686), y) OPTS += -DUSE_I686 -DEVBROBJ += m_at_socket8.o endif ifeq ($(LASERXT), y) @@ -512,8 +528,12 @@ ifeq ($(VECTRA54), y) OPTS += -DUSE_VECTRA54 endif -ifeq ($(MICRONICS386), y) -OPTS += -DUSE_MICRONICS386 +ifeq ($(VPP60), y) +OPTS += -DUSE_VPP60 +endif + +ifeq ($(SIEMENS), y) +OPTS += -DUSE_SIEMENS endif ifeq ($(VGAWONDER), y) @@ -536,7 +556,7 @@ endif # Final versions of the toolchain flags. CFLAGS := $(WX_FLAGS) $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ $(AFLAGS) -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing -funroll-loops + -fno-strict-aliasing # Add freetyp2 references through pkgconfig CFLAGS := $(CFLAGS) `pkg-config.exe --cflags freetype2` @@ -548,24 +568,25 @@ CXXFLAGS := $(CFLAGS) # Create the (final) list of objects to build. # ######################################################################### MAINOBJ := pc.o config.o random.o timer.o io.o apm_new.o dma.o nmi.o \ - pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem_new.o \ - rom.o device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) + pic.o pit.o port_92.o ppi.o pci.o mca.o mcr.o mem.o \ + rom.o device.o nvr.o nvr_at.o nvr_ps2.o sst_flash.o via_vt82c586b.o $(VNCOBJ) $(RDPOBJ) INTELOBJ := intel_flash.o \ intel_sio.o intel_piix.o CPUOBJ := cpu.o cpu_table.o \ - 808x.o 386.o 386_common.o \ + 808x.o \ + 386.o 386_common.o \ 386_dynarec.o \ x86seg.o x87.o \ $(DYNARECOBJ) CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \ - intel_4x0.o neat.o opti495.o scat.o \ + intel_4x0.o neat.o opti495.o scamp.o scat.o \ sis_85c471.o sis_85c496.o \ - wd76c10.o + via_mvp3.o wd76c10.o -MCHOBJ := machine.o machine_table_new.o \ +MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \ m_xt_t1000.o m_xt_t1000_vid.o \ m_xt_xi8088.o m_xt_zenith.o \ @@ -578,14 +599,18 @@ MCHOBJ := machine.o machine_table_new.o \ m_ps2_isa.o m_ps2_mca.o \ m_at_compaq.o \ m_at_286_386sx.o m_at_386dx_486.o \ - m_at_socket4_5.o m_at_socket7_s7.o + m_at_socket4_5.o m_at_socket7_s7.o \ + m_at_socket8.o -DEVOBJ := bugger.o ibm_5161.o isamem.o isartc.o lpt.o $(SERIAL) \ +DEVOBJ := bugger.o hwm.o hwm_w83781d.o ibm_5161.o isamem.o isartc.o lpt.o postcard.o $(SERIAL) \ sio_acc3221.o \ sio_fdc37c66x.o sio_fdc37c669.o \ sio_fdc37c93x.o \ - sio_pc87306.o sio_w83877f.o \ + sio_pc87306.o \ + sio_w83787f.o \ + sio_w83877f.o sio_w83977f.o \ sio_um8669f.o \ + smbus.o \ keyboard.o \ keyboard_xt.o keyboard_at.o \ gameport.o \ @@ -622,7 +647,8 @@ SCSIOBJ := scsi.o scsi_device.o \ scsi_cdrom.o scsi_disk.o \ scsi_x54x.o \ scsi_aha154x.o scsi_buslogic.o \ - scsi_ncr5380.o scsi_ncr53c8xx.o + scsi_ncr5380.o scsi_ncr53c8xx.o \ + scsi_spock.o NETOBJ := network.o \ net_pcap.o \ @@ -684,6 +710,7 @@ VIDOBJ := video.o \ vid_et4000.o vid_sc1502x_ramdac.o \ vid_et4000w32.o vid_stg_ramdac.o \ vid_ht216.o \ + vid_mga.o \ vid_oak_oti.o \ vid_paradise.o \ vid_ti_cf62011.o \ diff --git a/src/win/resource.h b/src/win/resource.h index 8e11ed62a..c4ffc2728 100644 --- a/src/win/resource.h +++ b/src/win/resource.h @@ -175,7 +175,7 @@ #define IDC_CHECK_IDE_QUA 1127 #define IDC_BUTTON_IDE_QUA 1128 #define IDC_CHECK_BUGGER 1129 -#define IDC_CONFIGURE_BUGGER 1130 +#define IDC_CHECK_POSTCARD 1130 #define IDC_COMBO_ISARTC 1131 #define IDC_CONFIGURE_ISARTC 1132 #define IDC_GROUP_ISAMEM 1140 diff --git a/src/win/win.c b/src/win/win.c index 2f421412b..4197edd4c 100644 --- a/src/win/win.c +++ b/src/win/win.c @@ -30,18 +30,18 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../config.h" -#include "../device.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../video/video.h" +#include "86box.h" +#include "config.h" +#include "device.h" +#include "keyboard.h" +#include "mouse.h" +#include "video.h" #define GLOBAL -#include "../plat.h" -#include "../plat_midi.h" -#include "../ui.h" +#include "plat.h" +#include "plat_midi.h" +#include "ui.h" #ifdef USE_VNC -# include "../vnc.h" +# include "vnc.h" #endif # include "win_d2d.h" # include "win_sdl.h" @@ -73,6 +73,7 @@ static rc_str_t *lpRCstr2048, *lpRCstr6144, *lpRCstr7168; static int vid_api_inited = 0; +static wchar_t *argbuf; static const struct { @@ -267,6 +268,11 @@ CreateConsole(int init) } } } + + if (fp != NULL) { + fclose(fp); + fp = NULL; + } } @@ -275,7 +281,6 @@ static int ProcessCommandLine(wchar_t ***argw) { WCHAR *cmdline; - wchar_t *argbuf; wchar_t **args; int argc_max; int i, q, argc; @@ -376,6 +381,8 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) if (source_hwnd) PostMessage((HWND) (uintptr_t) source_hwnd, WM_HAS_SHUTDOWN, (WPARAM) 0, (LPARAM) hwndMain); + free(argbuf); + free(argw); return(1); } @@ -386,6 +393,8 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpszArg, int nCmdShow) /* Handle our GUI. */ i = ui_init(nCmdShow); + free(argbuf); + free(argw); return(i); } diff --git a/src/win/win.h b/src/win/win.h index c3717e72b..6c8444a33 100644 --- a/src/win/win.h +++ b/src/win/win.h @@ -88,8 +88,8 @@ extern HICON hIcon[256]; // extern int status_is_open; -extern char openfilestring[260]; -extern WCHAR wopenfilestring[260]; +extern char openfilestring[512]; +extern WCHAR wopenfilestring[512]; extern uint8_t filterindex; diff --git a/src/win/win_about.c b/src/win/win_about.c index ae0eea162..b714cf334 100644 --- a/src/win/win_about.c +++ b/src/win/win_about.c @@ -26,8 +26,8 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" +#include "86box.h" +#include "plat.h" #include "win.h" diff --git a/src/win/win_cdrom.c b/src/win/win_cdrom.c index b027f463f..e808ced53 100644 --- a/src/win/win_cdrom.c +++ b/src/win/win_cdrom.c @@ -27,14 +27,14 @@ #include #include #include -#include "../config.h" -#include "../disk/hdd.h" -#include "../scsi/scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" -#include "../scsi/scsi_disk.h" -#include "../plat.h" -#include "../ui.h" +#include "config.h" +#include "hdd.h" +#include "scsi_device.h" +#include "cdrom.h" +#include "zip.h" +#include "scsi_disk.h" +#include "plat.h" +#include "ui.h" #include "win.h" diff --git a/src/win/win_crashdump.c b/src/win/win_crashdump.c index 32944dbd0..cbec1b680 100644 --- a/src/win/win_crashdump.c +++ b/src/win/win_crashdump.c @@ -25,8 +25,8 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" +#include "86box.h" +#include "plat.h" #include "win.h" diff --git a/src/win/win_d2d.c b/src/win/win_d2d.c index 038ef739c..45ff1e83b 100644 --- a/src/win/win_d2d.c +++ b/src/win/win_d2d.c @@ -27,12 +27,12 @@ #undef BITMAP #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../video/video.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "video.h" +#include "plat.h" +#include "plat_dynld.h" +#include "ui.h" #include "win.h" #include "win_d2d.h" diff --git a/src/win/win_devconf.c b/src/win/win_devconf.c index e5e379d6c..fa925eb33 100644 --- a/src/win/win_devconf.c +++ b/src/win/win_devconf.c @@ -21,12 +21,12 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_midi.h" -#include "../ui.h" +#include "86box.h" +#include "config.h" +#include "device.h" +#include "plat.h" +#include "plat_midi.h" +#include "ui.h" #include "win.h" #include diff --git a/src/win/win_dialog.c b/src/win/win_dialog.c index a17d96953..1fca7cfd1 100644 --- a/src/win/win_dialog.c +++ b/src/win/win_dialog.c @@ -27,15 +27,15 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "ui.h" #include "win.h" -WCHAR wopenfilestring[260]; -char openfilestring[260]; +WCHAR wopenfilestring[512]; +char openfilestring[512]; uint8_t filterindex = 0; @@ -145,7 +145,7 @@ file_dlg_w(HWND hwnd, WCHAR *f, WCHAR *fn, int save) * not use the contents of szFile to initialize itself. */ memcpy(ofn.lpstrFile, fn, (wcslen(fn) << 1) + 2); - ofn.nMaxFile = 259; + ofn.nMaxFile = sizeof_w(wopenfilestring); ofn.lpstrFilter = f; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; diff --git a/src/win/win_discord.c b/src/win/win_discord.c index b402f10e8..04253b5b6 100644 --- a/src/win/win_discord.c +++ b/src/win/win_discord.c @@ -22,15 +22,11 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#ifdef USE_NEW_DYNAREC - #include "../cpu_new/cpu.h" -#else - #include "../cpu/cpu.h" -#endif -#include "../machine/machine.h" -#include "../plat.h" -#include "../plat_dynld.h" +#include "86box.h" +#include "cpu.h" +#include "machine.h" +#include "plat.h" +#include "plat_dynld.h" #include "win_discord.h" #include "discord_game_sdk.h" @@ -74,6 +70,7 @@ discord_update_activity(int paused) struct DiscordActivity activity; wchar_t config_name_w[1024]; char config_name[128]; + char *temp; if(discord_activities == NULL) return; @@ -90,8 +87,17 @@ discord_update_activity(int paused) } else { - strcpy(activity.details, strchr(machine_getname(), ']') + 2); - strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); + temp = strchr(machine_getname(), ']') + 2; + + if (strlen(temp) <= 127) + strcpy(activity.details, temp); + else + strncpy(activity.details, temp, 127); + + if (strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name) <= 127) + strcpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name); + else + strncpy(activity.state, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name, 127); } activity.timestamps.start = time(NULL); diff --git a/src/win/win_dynld.c b/src/win/win_dynld.c index 6043e36d6..b5e89aaff 100644 --- a/src/win/win_dynld.c +++ b/src/win/win_dynld.c @@ -22,8 +22,8 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../plat_dynld.h" +#include "86box.h" +#include "plat_dynld.h" #ifdef ENABLE_DYNLD_LOG @@ -65,7 +65,7 @@ dynld_module(const char *name, dllimp_t *table) if (func == NULL) { dynld_log("DynLd(\"%s\"): function '%s' not found!\n", name, imp->name); - CloseHandle(h); + FreeLibrary(h); return(NULL); } diff --git a/src/win/win_joystick.cpp b/src/win/win_joystick.cpp index d073cd37c..437b506e6 100644 --- a/src/win/win_joystick.cpp +++ b/src/win/win_joystick.cpp @@ -23,10 +23,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../game/gameport.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "gameport.h" #include "win.h" @@ -82,37 +82,54 @@ BOOL CALLBACK DIEnumDeviceObjectsCallback( plat_joystick_t *state = (plat_joystick_t *)pvRef; if (lpddoi->guidType == GUID_XAxis || lpddoi->guidType == GUID_YAxis || lpddoi->guidType == GUID_ZAxis || - lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis || - lpddoi->guidType == GUID_Slider) + lpddoi->guidType == GUID_RxAxis || lpddoi->guidType == GUID_RyAxis || lpddoi->guidType == GUID_RzAxis) { - memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); - if (lpddoi->guidType == GUID_XAxis) - state->axis[state->nr_axes].id = 0; - else if (lpddoi->guidType == GUID_YAxis) - state->axis[state->nr_axes].id = 1; - else if (lpddoi->guidType == GUID_ZAxis) - state->axis[state->nr_axes].id = 2; - else if (lpddoi->guidType == GUID_RxAxis) - state->axis[state->nr_axes].id = 3; - else if (lpddoi->guidType == GUID_RyAxis) - state->axis[state->nr_axes].id = 4; - else if (lpddoi->guidType == GUID_RzAxis) - state->axis[state->nr_axes].id = 5; - state->nr_axes++; + if (state->nr_axes < 8) + {memcpy(state->axis[state->nr_axes].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Axis %i : %s %x %x\n", state->nr_axes, state->axis[state->nr_axes].name, lpddoi->dwOfs, lpddoi->dwType); + if (lpddoi->guidType == GUID_XAxis) + state->axis[state->nr_axes].id = 0; + else if (lpddoi->guidType == GUID_YAxis) + state->axis[state->nr_axes].id = 1; + else if (lpddoi->guidType == GUID_ZAxis) + state->axis[state->nr_axes].id = 2; + else if (lpddoi->guidType == GUID_RxAxis) + state->axis[state->nr_axes].id = 3; + else if (lpddoi->guidType == GUID_RyAxis) + state->axis[state->nr_axes].id = 4; + else if (lpddoi->guidType == GUID_RzAxis) + state->axis[state->nr_axes].id = 5; + state->nr_axes++; + } } else if (lpddoi->guidType == GUID_Button) { - memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_buttons++; + if (state->nr_buttons < 32) + { + memcpy(state->button[state->nr_buttons].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("Button %i : %s %x %x\n", state->nr_buttons, state->button[state->nr_buttons].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_buttons++; + } } else if (lpddoi->guidType == GUID_POV) { - memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); - joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); - state->nr_povs++; - } + if (state->nr_povs < 4) + { + memcpy(state->pov[state->nr_povs].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + joystick_log("POV %i : %s %x %x\n", state->nr_povs, state->pov[state->nr_povs].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_povs++; + } + } + else if (lpddoi->guidType == GUID_Slider) + { + if (state->nr_sliders < 2) + { + memcpy(state->slider[state->nr_sliders].name, lpddoi->tszName, strlen(lpddoi->tszName) + 1); + state->slider[state->nr_sliders].id = state->nr_sliders | SLIDER; + joystick_log("Slider %i : %s %x %x\n", state->nr_sliders, state->slider[state->nr_sliders].name, lpddoi->dwOfs, lpddoi->dwType); + state->nr_sliders++; + } + } return DIENUM_CONTINUE; } @@ -187,7 +204,11 @@ void joystick_init() lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); joy_axis_range.diph.dwObj = DIJOFS_RZ; lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); - + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(0); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + joy_axis_range.diph.dwObj = DIJOFS_SLIDER(1); + lpdi_joystick[c]->SetProperty(DIPROP_RANGE, &joy_axis_range.diph); + if (FAILED(lpdi_joystick[c]->Acquire())) fatal("joystick_init : Acquire failed\n"); } @@ -226,6 +247,10 @@ static int joystick_get_axis(int joystick_nr, int mapping) return 0; else return -cos((2*M_PI * (double)pov) / 36000.0) * 32767; + } + else if (mapping & SLIDER) + { + return plat_joystick_state[joystick_nr].s[mapping & 3]; } else return plat_joystick_state[joystick_nr].a[plat_joystick_state[joystick_nr].axis[mapping].id]; @@ -235,7 +260,7 @@ void joystick_process(void) { int c, d; - if (joystick_type == 7) return; + if (joystick_type == JOYSTICK_TYPE_NONE) return; for (c = 0; c < joysticks_present; c++) { @@ -260,6 +285,8 @@ void joystick_process(void) plat_joystick_state[c].a[3] = joystate.lRx; plat_joystick_state[c].a[4] = joystate.lRy; plat_joystick_state[c].a[5] = joystate.lRz; + plat_joystick_state[c].s[0] = joystate.rglSlider[0]; + plat_joystick_state[c].s[1] = joystate.rglSlider[1]; for (b = 0; b < 16; b++) plat_joystick_state[c].b[b] = joystate.rgbButtons[b] & 0x80; diff --git a/src/win/win_joystick_xinput.cpp b/src/win/win_joystick_xinput.cpp index 6be292c13..5d3e2fbbb 100644 --- a/src/win/win_joystick_xinput.cpp +++ b/src/win/win_joystick_xinput.cpp @@ -24,10 +24,10 @@ #include #include #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../game/gameport.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "gameport.h" #include "win.h" #define XINPUT_MAX_JOYSTICKS 4 @@ -216,7 +216,7 @@ void joystick_process(void) { int c, d; - if (joystick_type == 7) return; + if (joystick_type == JOYSTICK_TYPE_NONE) return; joystick_poll(); diff --git a/src/win/win_jsconf.c b/src/win/win_jsconf.c index 1ca6f5ef8..b048afa27 100644 --- a/src/win/win_jsconf.c +++ b/src/win/win_jsconf.c @@ -7,11 +7,11 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../device.h" -#include "../game/gameport.h" -#include "../plat.h" +#include "86box.h" +#include "config.h" +#include "device.h" +#include "gameport.h" +#include "plat.h" #include "win.h" @@ -58,6 +58,10 @@ static void rebuild_axis_button_selections(HWND hdlg) SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); sprintf(s, "%s (Y axis)", plat_joystick_state[joystick-1].pov[d].name); SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)s); + } + for (d = 0; d < plat_joystick_state[joystick - 1].nr_sliders; d++) + { + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)plat_joystick_state[joystick - 1].slider[d].name); } SendMessage(h, CB_SETCURSEL, sel, 0); EnableWindow(h, TRUE); @@ -122,15 +126,23 @@ static int get_axis(HWND hdlg, int id) HWND h = GetDlgItem(hdlg, id); int axis_sel = SendMessage(h, CB_GETCURSEL, 0, 0); int nr_axes = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr-1].nr_axes; - + int nr_povs = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_povs; + int nr_sliders = plat_joystick_state[joystick_state[joystick_nr].plat_joystick_nr - 1].nr_sliders; + if (axis_sel < nr_axes) return axis_sel; axis_sel -= nr_axes; - if (axis_sel & 1) - return POV_Y | (axis_sel >> 1); - else - return POV_X | (axis_sel >> 1); + if (axis_sel < nr_povs * 2) + { + if (axis_sel & 1) + return POV_Y | (axis_sel >> 1); + else + return POV_X | (axis_sel >> 1); + } + axis_sel -= nr_povs; + + return SLIDER | (axis_sel >> 1); } static int get_pov(HWND hdlg, int id) @@ -163,6 +175,7 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) int joystick; int nr_axes; int nr_povs; + int nr_sliders; int mapping; switch (message) @@ -186,6 +199,8 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { nr_axes = plat_joystick_state[joystick-1].nr_axes; nr_povs = plat_joystick_state[joystick-1].nr_povs; + nr_sliders = plat_joystick_state[joystick - 1].nr_sliders; + for (c = 0; c < joystick_get_axis_count(joystick_config_type); c++) { int mapping = joystick_state[joystick_nr].axis_mapping[c]; @@ -195,7 +210,9 @@ joystickconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2, 0); else if (mapping & POV_Y) SendMessage(h, CB_SETCURSEL, nr_axes + (mapping & 3)*2 + 1, 0); - else + else if (mapping & SLIDER) + SendMessage(h, CB_SETCURSEL, nr_axes + nr_povs * 2 + (mapping & 3), 0); + else SendMessage(h, CB_SETCURSEL, mapping, 0); id += 2; } diff --git a/src/win/win_keyboard.c b/src/win/win_keyboard.c index eaf4ddac4..8fb761a44 100644 --- a/src/win/win_keyboard.c +++ b/src/win/win_keyboard.c @@ -24,10 +24,10 @@ #include #include #include -#include "../86box.h" -#include "../device.h" -#include "../keyboard.h" -#include "../plat.h" +#include "86box.h" +#include "device.h" +#include "keyboard.h" +#include "plat.h" #include "win.h" diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 256ab6a5e..c38f444fd 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -4,11 +4,11 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../sound/midi.h" -#include "../plat.h" -#include "../plat_midi.h" +#include "86box.h" +#include "config.h" +#include "midi.h" +#include "plat.h" +#include "plat_midi.h" typedef struct @@ -18,7 +18,7 @@ typedef struct HANDLE m_event; HMIDIOUT midi_out_device; - HMIDIIN midi_in_device; + HMIDIIN midi_in_device; MIDIHDR m_hdr; } plat_midi_t; @@ -137,57 +137,44 @@ plat_midi_write(uint8_t val) return 0; } + void CALLBACK plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - uint8_t msg[4] = {((dwParam1&0xff)),(((dwParam1&0xff00)>>8)), - (((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]}; - uint8_t *sysex; - uint32_t len; - int cnt; - MIDIHDR *hdr; - switch (wMsg) { - case MM_MIM_DATA: /* 0x3C3 - midi message */ - input_msg(midi_in_p, msg); - break; - case MM_MIM_OPEN: /* 0x3C1 */ - break; - case MM_MIM_CLOSE: /* 0x3C2 */ - break; - case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ - hdr = (MIDIHDR *)dwParam1; - sysex = (uint8_t *)hdr->lpData; - len = (uint32_t)hdr->dwBytesRecorded; - cnt = 5; - while (cnt) { /*abort if timed out*/ - int ret = input_sysex(midi_in_p, sysex, len, 0); - if (!ret) { - len = 0; - break; - } - if (len==ret) - cnt--; - else - cnt = 5; - sysex += len-ret; - len = ret; - Sleep(5);/*msec*/ - } - if (len) - input_sysex(midi_in_p, sysex, 0, 0); - - midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr)); - hdr->dwBytesRecorded = 0; - midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr)); - break; - case MM_MIM_ERROR: - case MM_MIM_LONGERROR: - break; - default: - break; - } + uint8_t msg[4] = { ((dwParam1 & 0xff)), (((dwParam1 & 0xff00) >> 8)), + (((dwParam1 & 0xff0000) >> 16)), MIDI_evt_len[((dwParam1 & 0xff))]}; + uint8_t *sysex; + uint32_t len; + MIDIHDR *hdr; + + switch (wMsg) { + case MM_MIM_DATA: /* 0x3C3 - midi message */ + midi_in_msg(msg); + break; + case MM_MIM_OPEN: /* 0x3C1 */ + break; + case MM_MIM_CLOSE: /* 0x3C2 */ + break; + case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ + /* It is midi_in_sysex() that now does the loop. */ + hdr = (MIDIHDR *) dwParam1; + sysex = (uint8_t *) hdr->lpData; + len = (uint32_t) hdr->dwBytesRecorded; + midi_in_sysex(sysex, len); + + midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr)); + hdr->dwBytesRecorded = 0; + midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr)); + break; + case MM_MIM_ERROR: + case MM_MIM_LONGERROR: + break; + default: + break; + } } + void plat_midi_input_init(void) { @@ -197,11 +184,11 @@ plat_midi_input_init(void) memset(pm_in, 0, sizeof(plat_midi_t)); pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0); - - hr = MMSYSERR_NOERROR; - + + hr = MMSYSERR_NOERROR; + hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id, - (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); + (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); if (hr != MMSYSERR_NOERROR) { printf("midiInOpen error - %08X\n", hr); pm_in->midi_input_id = 0; @@ -212,15 +199,16 @@ plat_midi_input_init(void) return; } } - - pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0]; - pm_in->m_hdr.dwBufferLength = SYSEX_SIZE; - pm_in->m_hdr.dwBytesRecorded = 0; - pm_in->m_hdr.dwUser = 0; - midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr)); - midiInStart(pm_in->midi_in_device); + + pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0]; + pm_in->m_hdr.dwBufferLength = SYSEX_SIZE; + pm_in->m_hdr.dwBytesRecorded = 0; + pm_in->m_hdr.dwUser = 0; + midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr)); + midiInStart(pm_in->midi_in_device); } + void plat_midi_input_close(void) { @@ -235,6 +223,7 @@ plat_midi_input_close(void) } } + int plat_midi_in_get_num_devs(void) { @@ -249,4 +238,4 @@ plat_midi_in_get_dev_name(int num, char *s) midiInGetDevCaps(num, &caps, sizeof(caps)); strcpy(s, caps.szPname); -} \ No newline at end of file +} diff --git a/src/win/win_mouse.c b/src/win/win_mouse.c index 2ca004e9f..f58f4be82 100644 --- a/src/win/win_mouse.c +++ b/src/win/win_mouse.c @@ -22,9 +22,9 @@ #include #include #include -#include "../86box.h" -#include "../mouse.h" -#include "../plat.h" +#include "86box.h" +#include "mouse.h" +#include "plat.h" #include "win.h" int mouse_capture; diff --git a/src/win/win_new_floppy.c b/src/win/win_new_floppy.c index 0dff080c9..bbae1551e 100644 --- a/src/win/win_new_floppy.c +++ b/src/win/win_new_floppy.c @@ -25,12 +25,12 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" -#include "../random.h" -#include "../ui.h" -#include "../scsi/scsi_device.h" -#include "../disk/zip.h" +#include "86box.h" +#include "plat.h" +#include "random.h" +#include "ui.h" +#include "scsi_device.h" +#include "zip.h" #include "win.h" @@ -80,7 +80,7 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) uint16_t tflags = 0; uint32_t index_hole_pos = 0; uint32_t tarray[512]; - uint32_t array_size, array_size2; + uint32_t array_size; uint32_t track_base, track_size; int i; uint32_t shift = 0; @@ -133,11 +133,6 @@ create_86f(WCHAR *file_name, disk_size_t disk_size, uint8_t rpm_mode) break; } - array_size2 = (array_size << 3); - array_size = (array_size2 >> 4) << 1; - if (array_size2 & 15) - array_size += 2; - empty = (unsigned char *) malloc(array_size); memset(tarray, 0, 2048); @@ -515,7 +510,7 @@ create_zip_sector_image(WCHAR *file_name, disk_size_t disk_size, uint8_t is_zdi, static int fdd_id, sb_part; static int file_type = 0; /* 0 = IMG, 1 = Japanese FDI, 2 = 86F */ -static wchar_t fd_file_name[512]; +static wchar_t fd_file_name[1024]; /* Show a MessageBox dialog. This is nasty, I know. --FvK */ @@ -556,7 +551,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: plat_pause(1); - memset(fd_file_name, 0, 512 * sizeof(wchar_t)); + memset(fd_file_name, 0, 1024 * sizeof(wchar_t)); h = GetDlgItem(hdlg, IDC_COMBO_DISK_SIZE); if (is_zip) { zip_types = zip_drives[fdd_id].is_250 ? 2 : 1; @@ -613,6 +608,7 @@ NewFloppyDialogProcedure(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) new_floppy_msgbox(hdlg, MBX_ERROR, (wchar_t *)IDS_4108); return TRUE; } + /*FALLTHROUGH*/ case IDCANCEL: EndDialog(hdlg, 0); plat_pause(0); diff --git a/src/win/win_opendir.c b/src/win/win_opendir.c index bcd683c3d..74309eb25 100644 --- a/src/win/win_opendir.c +++ b/src/win/win_opendir.c @@ -25,8 +25,8 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" +#include "86box.h" +#include "plat.h" #include "plat_dir.h" diff --git a/src/win/win_sdl.c b/src/win/win_sdl.c index 762f4c5db..f4c415d11 100644 --- a/src/win/win_sdl.c +++ b/src/win/win_sdl.c @@ -12,13 +12,13 @@ * we will not use that, but, instead, use a new window which * coverrs the entire desktop. * - * Version: @(#)win_sdl.c 1.0.10 2019/12/06 + * Version: @(#)win_sdl.c 1.0.11 2020/01/22 * * Authors: Fred N. van Kempen, * Michael Drüing, * - * Copyright 2018,2019 Fred N. van Kempen. - * Copyright 2018,2019 Michael Drüing. + * Copyright 2018-2020 Fred N. van Kempen. + * Copyright 2018-2020 Michael Drüing. * * Redistribution and use in source and binary forms, with * or without modification, are permitted provided that the @@ -62,12 +62,12 @@ /* This #undef is needed because a SDL include header redefines HAVE_STDARG_H. */ #undef HAVE_STDARG_H #define HAVE_STDARG_H -#include "../86box.h" -#include "../device.h" -#include "../plat.h" -#include "../plat_dynld.h" -#include "../video/video.h" -#include "../ui.h" +#include "86box.h" +#include "device.h" +#include "plat.h" +#include "plat_dynld.h" +#include "video.h" +#include "ui.h" #include "win.h" #include "win_sdl.h" @@ -108,10 +108,31 @@ sdl_log(const char *fmt, ...) #endif +static void +sdl_integer_scale(double *d, double *g) +{ + double ratio; + + if (*d > *g) { + ratio = floor(*d / *g); + *d = *g * ratio; + } else { + ratio = ceil(*d / *g); + *d = *g / ratio; + } +} + + static void sdl_stretch(int *w, int *h, int *x, int *y) { - double dw, dh, dx, dy, temp, temp2, ratio_w, ratio_h, gsr, hsr; + double hw, gw, hh, gh, dx, dy, dw, dh, gsr, hsr; + + hw = (double) sdl_w; + hh = (double) sdl_h; + gw = (double) *w; + gh = (double) *h; + hsr = hw / hh; switch (video_fullscreen_scale) { case FULLSCR_SCALE_FULL: @@ -122,44 +143,37 @@ sdl_stretch(int *w, int *h, int *x, int *y) break; case FULLSCR_SCALE_43: case FULLSCR_SCALE_KEEPRATIO: - dw = (double) sdl_w; - dh = (double) sdl_h; - hsr = dw / dh; if (video_fullscreen_scale == FULLSCR_SCALE_43) gsr = 4.0 / 3.0; else - gsr = ((double) *w) / ((double) *h); + gsr = gw / gh; if (gsr <= hsr) { - temp = dh * gsr; - dx = (dw - temp) / 2.0; - dw = temp; - *w = (int) dw; - *h = (int) dh; - *x = (int) dx; - *y = 0; + dw = hh * gsr; + dh = hh; } else { - temp = dw / gsr; - dy = (dh - temp) / 2.0; - dh = temp; - *w = (int) dw; - *h = (int) dh; - *x = 0; - *y = (int) dy; + dw = hw; + dh = hw / gsr; } + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; + *w = (int) hw; + *h = (int) hh; + *x = (int) dx; + *y = (int) dy; break; case FULLSCR_SCALE_INT: - dw = (double) sdl_w; - dh = (double) sdl_h; - temp = ((double) *w); - temp2 = ((double) *h); - ratio_w = dw / ((double) *w); - ratio_h = dh / ((double) *h); - if (ratio_h < ratio_w) - ratio_w = ratio_h; - dx = (dw / 2.0) - ((temp * ratio_w) / 2.0); - dy = (dh / 2.0) - ((temp2 * ratio_h) / 2.0); - dw -= (dx * 2.0); - dh -= (dy * 2.0); + gsr = gw / gh; + if (gsr <= hsr) { + dw = hh * gsr; + dh = hh; + } else { + dw = hw; + dh = hw / gsr; + } + sdl_integer_scale(&dw, &gw); + sdl_integer_scale(&dh, &gh); + dx = (hw - dw) / 2.0; + dy = (hh - dh) / 2.0; *w = (int) dw; *h = (int) dh; *x = (int) dx; diff --git a/src/win/win_settings.c b/src/win/win_settings.c index f47f4f4b1..6d5476295 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -30,38 +30,36 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../cpu/cpu.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../timer.h" -#include "../nvr.h" -#include "../machine/machine.h" -#include "../game/gameport.h" -#include "../isamem.h" -#include "../isartc.h" -#include "../lpt.h" -#include "../mouse.h" -#include "../scsi/scsi.h" -#include "../scsi/scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../disk/hdd.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../disk/zip.h" -#include "../floppy/fdd.h" -#include "../network/network.h" -#include "../sound/sound.h" -#include "../sound/midi.h" -#include "../sound/snd_mpu401.h" -#include "../sound/snd_gus.h" -#include "../video/video.h" -#include "../video/vid_voodoo.h" -#include "../plat.h" -#include "../plat_midi.h" -#include "../ui.h" +#include "86box.h" +#include "config.h" +#include "cpu.h" +#include "mem.h" +#include "rom.h" +#include "device.h" +#include "timer.h" +#include "nvr.h" +#include "machine.h" +#include "gameport.h" +#include "isamem.h" +#include "isartc.h" +#include "lpt.h" +#include "mouse.h" +#include "scsi.h" +#include "scsi_device.h" +#include "cdrom.h" +#include "hdd.h" +#include "hdc.h" +#include "hdc_ide.h" +#include "zip.h" +#include "fdd.h" +#include "network.h" +#include "sound.h" +#include "midi.h" +#include "snd_mpu401.h" +#include "video.h" +#include "plat.h" +#include "plat_midi.h" +#include "ui.h" #include "win.h" @@ -99,6 +97,7 @@ static int temp_serial[2], temp_lpt[3]; /* Other peripherals category */ static int temp_hdc, temp_scsi_card, temp_ide_ter, temp_ide_qua; static int temp_bugger; +static int temp_postcard; static int temp_isartc; static int temp_isamem[ISAMEM_MAX]; @@ -250,6 +249,7 @@ win_settings_init(void) temp_ide_ter = ide_ter_enabled; temp_ide_qua = ide_qua_enabled; temp_bugger = bugger_enabled; + temp_postcard = postcard_enabled; temp_isartc = isartc_type; /* ISA memory boards. */ @@ -358,6 +358,7 @@ win_settings_changed(void) i = i || (temp_ide_ter != ide_ter_enabled); i = i || (temp_ide_qua != ide_qua_enabled); i = i || (temp_bugger != bugger_enabled); + i = i || (temp_postcard != postcard_enabled); i = i || (temp_isartc != isartc_type); /* ISA memory boards. */ @@ -462,6 +463,7 @@ win_settings_save(void) ide_ter_enabled = temp_ide_ter; ide_qua_enabled = temp_ide_qua; bugger_enabled = temp_bugger; + postcard_enabled = temp_postcard; isartc_type = temp_isartc; /* ISA memory boards. */ @@ -539,13 +541,9 @@ win_settings_machine_recalc_cpu(HWND hdlg) h = GetDlgItem(hdlg, IDC_CHECK_FPU); cpu_type = machines[temp_machine].cpu[temp_cpu_m].cpus[temp_cpu].cpu_type; - // if ((cpu_type < CPU_i486DX) && (cpu_type >= CPU_286)) if (cpu_type < CPU_i486DX) EnableWindow(h, TRUE); - else if (cpu_type < CPU_286) { - temp_fpu = 0; - EnableWindow(h, FALSE); - } else { + else { temp_fpu = 1; EnableWindow(h, FALSE); } @@ -975,6 +973,7 @@ static BOOL CALLBACK win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) { wchar_t str[128]; + char *joy_name; HWND h; int c, d; @@ -1004,9 +1003,15 @@ win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) h = GetDlgItem(hdlg, IDC_COMBO_JOYSTICK); c = 0; - while (joystick_get_name(c)) { - SendMessage(h, CB_ADDSTRING, 0, win_get_string(2105 + c)); + joy_name = joystick_get_name(c); + while (joy_name) + { + mbstowcs(str, joy_name, strlen(joy_name) + 1); + SendMessage(h, CB_ADDSTRING, 0, (LPARAM)str); + + // SendMessage(h, CB_ADDSTRING, 0, win_get_string(2105 + c)); c++; + joy_name = joystick_get_name(c); } EnableWindow(h, TRUE); SendMessage(h, CB_SETCURSEL, temp_joystick, 0); @@ -1593,6 +1598,9 @@ win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPa h=GetDlgItem(hdlg, IDC_CHECK_BUGGER); SendMessage(h, BM_SETCHECK, temp_bugger, 0); + h=GetDlgItem(hdlg, IDC_CHECK_POSTCARD); + SendMessage(h, BM_SETCHECK, temp_postcard, 0); + /* Populate the ISA RTC card dropdown. */ e = 0; h = GetDlgItem(hdlg, IDC_COMBO_ISARTC); @@ -1796,6 +1804,9 @@ win_settings_peripherals_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lPa h = GetDlgItem(hdlg, IDC_CHECK_BUGGER); temp_bugger = SendMessage(h, BM_GETCHECK, 0, 0); + h = GetDlgItem(hdlg, IDC_CHECK_POSTCARD); + temp_postcard = SendMessage(h, BM_GETCHECK, 0, 0); + free(stransi); free(lptsTemp); @@ -2532,7 +2543,7 @@ static int hdconf_initialize_hdt_combo(HWND hdlg) h = GetDlgItem(hdlg, IDC_COMBO_HD_TYPE); for (i = 0; i < 127; i++) { - temp_size = hdd_table[i][0] * hdd_table[i][1] * hdd_table[i][2]; + temp_size = ((uint64_t) hdd_table[i][0]) * hdd_table[i][1] * hdd_table[i][2]; size_mb = (uint32_t) (temp_size >> 11LL); wsprintf(szText, plat_get_string(IDS_2116), size_mb, hdd_table[i][0], hdd_table[i][1], hdd_table[i][2]); SendMessage(h, CB_ADDSTRING, 0, (LPARAM) szText); @@ -2850,6 +2861,7 @@ win_settings_hard_disks_add_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM f = _wfopen(wopenfilestring, (existing & 1) ? L"rb" : L"wb"); if (f == NULL) { hdd_add_file_open_error: + fclose(f); settings_msgbox(MBX_ERROR, (existing & 1) ? (wchar_t *)IDS_4107 : (wchar_t *)IDS_4108); return TRUE; } @@ -2880,7 +2892,6 @@ hdd_add_file_open_error: } else { fseeko64(f, 0, SEEK_END); size = ftello64(f); - fclose(f); if (((size % 17) == 0) && (size <= 142606336)) { spt = 17; if (size <= 26738688) @@ -2928,8 +2939,9 @@ hdd_add_file_open_error: chs_enabled = 1; no_update = 0; - } else - fclose(f); + } + + fclose(f); } h = GetDlgItem(hdlg, IDC_EDIT_HD_FILE_NAME); @@ -3467,7 +3479,7 @@ win_settings_floppy_drives_recalc_list(HWND hwndList) { LVITEM lvI; int i = 0; - char s[256]; + char s[256], *t; WCHAR szText[256]; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; @@ -3476,7 +3488,11 @@ win_settings_floppy_drives_recalc_list(HWND hwndList) for (i = 0; i < 4; i++) { lvI.iSubItem = 0; if (temp_fdd_types[i] > 0) { - strcpy(s, fdd_getname(temp_fdd_types[i])); + t = fdd_getname(temp_fdd_types[i]); + if (strlen(t) <= 256) + strcpy(s, t); + else + strncpy(s, t, 256); mbstowcs(szText, s, strlen(s) + 1); lvI.pszText = szText; } else @@ -3731,7 +3747,7 @@ static void win_settings_floppy_drives_update_item(HWND hwndList, int i) { LVITEM lvI; - char s[256]; + char s[256], *t; WCHAR szText[256]; lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; @@ -3741,7 +3757,11 @@ win_settings_floppy_drives_update_item(HWND hwndList, int i) lvI.iItem = i; if (temp_fdd_types[i] > 0) { - strcpy(s, fdd_getname(temp_fdd_types[i])); + t = fdd_getname(temp_fdd_types[i]); + if (strlen(t) <= 256) + strcpy(s, t); + else + strncpy(s, t, 256); mbstowcs(szText, s, strlen(s) + 1); lvI.pszText = szText; } else diff --git a/src/win/win_snd_gain.c b/src/win/win_snd_gain.c index 0dc4e5dcc..7f23a1aee 100644 --- a/src/win/win_snd_gain.c +++ b/src/win/win_snd_gain.c @@ -25,10 +25,10 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../plat.h" -#include "../sound/sound.h" +#include "86box.h" +#include "config.h" +#include "plat.h" +#include "sound.h" #include "win.h" diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index ede2cb271..43554f159 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -28,27 +28,27 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../cpu/cpu.h" -#include "../device.h" -#include "../machine/machine.h" -#include "../timer.h" -#include "../disk/hdd.h" -#include "../disk/hdc.h" -#include "../floppy/fdd.h" -#include "../floppy/fdd_86f.h" -#include "../scsi/scsi.h" -#include "../scsi/scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" -#include "../cdrom/cdrom_image.h" -#include "../scsi/scsi_disk.h" -#include "../network/network.h" -#include "../video/video.h" -#include "../sound/sound.h" -#include "../plat.h" -#include "../ui.h" +#include "86box.h" +#include "config.h" +#include "cpu.h" +#include "device.h" +#include "machine.h" +#include "timer.h" +#include "hdd.h" +#include "hdc.h" +#include "fdd.h" +#include "fdd_86f.h" +#include "scsi.h" +#include "scsi_device.h" +#include "cdrom.h" +#include "zip.h" +#include "cdrom_image.h" +#include "scsi_disk.h" +#include "network.h" +#include "video.h" +#include "sound.h" +#include "plat.h" +#include "ui.h" #include "win.h" #ifndef GWL_WNDPROC diff --git a/src/win/win_thread.c b/src/win/win_thread.c index 2f885ec04..31a087cab 100644 --- a/src/win/win_thread.c +++ b/src/win/win_thread.c @@ -27,8 +27,8 @@ #include #include #include -#include "../86box.h" -#include "../plat.h" +#include "86box.h" +#include "plat.h" typedef struct { diff --git a/src/win/win_ui.c b/src/win/win_ui.c index 71f89a83b..df7a549c7 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -8,16 +8,16 @@ * * user Interface module for WinAPI on Windows. * - * Version: @(#)win_ui.c 1.0.45 2019/12/05 + * Version: @(#)win_ui.c 1.0.46 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * Fred N. van Kempen, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. - * Copyright 2017-2019 Fred N. van Kempen. - * Copyright 2019 GH Cao. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2019,2020 GH Cao. */ #define UNICODE #include @@ -28,16 +28,16 @@ #include #include #include -#include "../86box.h" -#include "../config.h" -#include "../device.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../video/video.h" -#include "../video/vid_ega.h" // for update_overscan -#include "../plat.h" -#include "../plat_midi.h" -#include "../ui.h" +#include "86box.h" +#include "config.h" +#include "device.h" +#include "keyboard.h" +#include "mouse.h" +#include "video.h" +#include "vid_ega.h" // for update_overscan +#include "plat.h" +#include "plat_midi.h" +#include "ui.h" #include "win.h" #ifdef USE_DISCORD # include "win_discord.h" @@ -59,8 +59,8 @@ int infocus = 1; int rctrl_is_lalt = 0; int user_resize = 0; -char openfilestring[260]; -WCHAR wopenfilestring[260]; +char openfilestring[512]; +WCHAR wopenfilestring[512]; /* Local data. */ @@ -333,7 +333,10 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case IDM_ACTION_EXIT: win_notify_dlg_open(); - i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); + if (no_quit_confirm) + i = 0; + else + i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); if (i == 0) { UnhookWindowsHookEx(hKeyboardHook); KillTimer(hwnd, TIMER_1SEC); @@ -628,8 +631,6 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) plat_vidapi_enable(0); temp_y -= sbar_height; - if (temp_x < 1) - temp_x = 1; if (temp_y < 1) temp_y = 1; @@ -700,7 +701,10 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_CLOSE: win_notify_dlg_open(); - i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); + if (no_quit_confirm) + i = 0; + else + i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); if (i == 0) { UnhookWindowsHookEx(hKeyboardHook); KillTimer(hwnd, TIMER_1SEC); @@ -746,7 +750,10 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (manager_wm) break; win_notify_dlg_open(); - i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); + if (no_quit_confirm) + i = 0; + else + i = ui_msgbox(MBX_QUESTION_YN, (wchar_t *)IDS_2122); if (i == 0) { UnhookWindowsHookEx(hKeyboardHook); KillTimer(hwnd, TIMER_1SEC); @@ -1099,9 +1106,12 @@ wchar_t * ui_window_title(wchar_t *s) { if (! video_fullscreen) { - if (s != NULL) - wcscpy(wTitle, s); - else + if (s != NULL) { + if (wcslen(s) <= 512) + wcscpy(wTitle, s); + else + wcsncpy(wTitle, s, 512); + } else s = wTitle; SetWindowText(hwndMain, s); @@ -1119,7 +1129,7 @@ void plat_pause(int p) { static wchar_t oldtitle[512]; - wchar_t title[512]; + wchar_t title[512], *t; /* If un-pausing, as the renderer if that's OK. */ if (p == 0) @@ -1135,7 +1145,11 @@ plat_pause(int p) } if (p) { - wcscpy(oldtitle, ui_window_title(NULL)); + t = ui_window_title(NULL); + if (wcslen(t) <= 511) + wcscpy(oldtitle, ui_window_title(NULL)); + else + wcsncpy(oldtitle, ui_window_title(NULL), 511); wcscpy(title, oldtitle); wcscat(title, L" - PAUSED -"); ui_window_title(title); diff --git a/src/x87_bak/x87.h b/src/x87_bak/x87.h new file mode 100644 index 000000000..be30c280c --- /dev/null +++ b/src/x87_bak/x87.h @@ -0,0 +1,58 @@ +#define C0 (1<<8) +#define C1 (1<<9) +#define C2 (1<<10) +#define C3 (1<<14) + +uint32_t x87_pc_off,x87_op_off; +uint16_t x87_pc_seg,x87_op_seg; + +static inline void x87_set_mmx() +{ +#ifdef USE_NEW_DYNAREC + cpu_state.TOP = 0; + *(uint64_t *)cpu_state.tag = 0x0101010101010101ull; + cpu_state.ismmx = 1; +#else + uint64_t *p; + cpu_state.TOP = 0; + p = (uint64_t *)cpu_state.tag; + *p = 0; + cpu_state.ismmx = 1; +#endif +} + +static inline void x87_emms() +{ +#ifdef USE_NEW_DYNAREC + *(uint64_t *)cpu_state.tag = 0; + cpu_state.ismmx = 0; +#else + uint64_t *p; + p = (uint64_t *)cpu_state.tag; + *p = 0; + cpu_state.ismmx = 0; +#endif +} + + +uint16_t x87_gettag(); +void x87_settag(uint16_t new_tag); + +#ifdef USE_NEW_DYNAREC +#define TAG_EMPTY 0 +#define TAG_VALID (1 << 0) +/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ +#define TAG_UINT64 (1 << 7) + +#define X87_ROUNDING_NEAREST 0 +#define X87_ROUNDING_DOWN 1 +#define X87_ROUNDING_UP 2 +#define X87_ROUNDING_CHOP 3 + +void codegen_set_rounding_mode(int mode); +#else +#define TAG_EMPTY 0 +#define TAG_VALID (1 << 0) +/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/ +#define TAG_UINT64 (1 << 2) +#endif diff --git a/src/cpu_new/x87_ops.h b/src/x87_bak/x87_ops.h similarity index 96% rename from src/cpu_new/x87_ops.h rename to src/x87_bak/x87_ops.h index 783a49382..57416251f 100644 --- a/src/cpu_new/x87_ops.h +++ b/src/x87_bak/x87_ops.h @@ -25,6 +25,7 @@ #ifdef _MSC_VER # include #endif +// #include "x87_timings.h" #ifdef ENABLE_FPU_LOG extern void fpu_log(const char *fmt, ...); @@ -81,18 +82,24 @@ static int rounding_modes[4] = {FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZ } while (0) #endif -static inline void x87_checkexceptions() +static __inline void x87_checkexceptions() { } -static inline void x87_push(double i) +static __inline void x87_push(double i) { +#ifdef USE_NEW_DYNAREC cpu_state.TOP--; cpu_state.ST[cpu_state.TOP&7] = i; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#else + cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.ST[cpu_state.TOP] = i; + cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0; +#endif } -static inline void x87_push_u64(uint64_t i) +static __inline void x87_push_u64(uint64_t i) { union { @@ -102,26 +109,75 @@ static inline void x87_push_u64(uint64_t i) td.ll = i; +#ifdef USE_NEW_DYNAREC cpu_state.TOP--; cpu_state.ST[cpu_state.TOP&7] = td.d; cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#else + cpu_state.TOP=(cpu_state.TOP-1)&7; + cpu_state.ST[cpu_state.TOP] = td.d; + cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0; +#endif } -static inline double x87_pop() +static __inline double x87_pop() { +#ifdef USE_NEW_DYNAREC double t = cpu_state.ST[cpu_state.TOP&7]; cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY; cpu_state.TOP++; return t; +#else + double t = cpu_state.ST[cpu_state.TOP]; + cpu_state.tag[cpu_state.TOP&7] = 3; + cpu_state.TOP=(cpu_state.TOP+1)&7; + return t; +#endif } -static inline int64_t x87_fround(double b) +static int old_round = FE_TONEAREST; + +static __inline int64_t x87_round_save(void) { + old_round = fetgetround(); +} + +static __inline int64_t x87_round_set(void) +{ + old_round = fetgetround(); + + switch ((cpu_state.npxc >> 10) & 3) { + case 0: /*Nearest*/ + fesetround(FE_TONEAREST); + break; + case 1: /*Down*/ + fesetround(FE_DOWNWARD); + break; + case 2: /*Up*/ + fesetround(FE_UPWARD); + break; + case 3: /*Chop*/ + fesetround(FE_TOWARDZERO); + break; + } +} + +static __inline int64_t x87_round_restore(void) +{ + fesetround(old_round); +} + +#ifdef PCEM_CODE +static __inline int64_t x87_fround(double b) +{ +#ifdef PCEM_CODE int64_t a, c; +#endif switch ((cpu_state.npxc >> 10) & 3) { case 0: /*Nearest*/ +#ifdef PCEM_CODE a = (int64_t)floor(b); c = (int64_t)floor(b + 1.0); if ((b - a) < (c - b)) @@ -130,21 +186,44 @@ static inline int64_t x87_fround(double b) return c; else return (a & 1) ? c : a; +#else + return (int64_t)round(b); +#endif case 1: /*Down*/ return (int64_t)floor(b); case 2: /*Up*/ return (int64_t)ceil(b); case 3: /*Chop*/ +#ifdef PCEM_CODE return (int64_t)b; +#else + return (int64_t)trunc(b); +#endif } return 0; } +#else +static __inline int64_t x87_fround(double b) +{ + int64_t ret; + + x87_round_set(); + ret = (int64_t) rint(b); + x87_round_restore(); +} +#endif #define BIAS80 16383 #define BIAS64 1023 -static inline double x87_ld80() +static __inline double x87_ld80() { + int64_t exp64; + int64_t blah; + int64_t exp64final; + int64_t mant64; + int64_t sign; + struct { int16_t begin; union @@ -153,16 +232,17 @@ static inline double x87_ld80() uint64_t ll; } eind; } test; + test.eind.ll = readmeml(easeg,cpu_state.eaaddr); test.eind.ll |= (uint64_t)readmeml(easeg,cpu_state.eaaddr+4)<<32; test.begin = readmemw(easeg,cpu_state.eaaddr+8); - int64_t exp64 = (((test.begin&0x7fff) - BIAS80)); - int64_t blah = ((exp64 >0)?exp64:-exp64)&0x3ff; - int64_t exp64final = ((exp64 >0)?blah:-blah) +BIAS64; + exp64 = (((test.begin&0x7fff) - BIAS80)); + blah = ((exp64 >0)?exp64:-exp64)&0x3ff; + exp64final = ((exp64 >0)?blah:-blah) +BIAS64; - int64_t mant64 = (test.eind.ll >> 11) & (0xfffffffffffff); - int64_t sign = (test.begin&0x8000)?1:0; + mant64 = (test.eind.ll >> 11) & (0xfffffffffffffll); + sign = (test.begin&0x8000)?1:0; if ((test.begin & 0x7fff) == 0x7fff) exp64final = 0x7ff; @@ -176,8 +256,14 @@ static inline double x87_ld80() return test.eind.d; } -static inline void x87_st80(double d) +static __inline void x87_st80(double d) { + int64_t sign80; + int64_t exp80; + int64_t exp80final; + int64_t mant80; + int64_t mant80final; + struct { int16_t begin; union @@ -189,32 +275,32 @@ static inline void x87_st80(double d) test.eind.d=d; - int64_t sign80 = (test.eind.ll&(0x8000000000000000))?1:0; - int64_t exp80 = test.eind.ll&(0x7ff0000000000000); - int64_t exp80final = (exp80>>52); - int64_t mant80 = test.eind.ll&(0x000fffffffffffff); - int64_t mant80final = (mant80 << 11); + sign80 = (test.eind.ll&(0x8000000000000000ll))?1:0; + exp80 = test.eind.ll&(0x7ff0000000000000ll); + exp80final = (exp80>>52); + mant80 = test.eind.ll&(0x000fffffffffffffll); + mant80final = (mant80 << 11); if (exp80final == 0x7ff) /*Infinity / Nan*/ { exp80final = 0x7fff; - mant80final |= (0x8000000000000000); + mant80final |= (0x8000000000000000ll); } - else if (d != 0){ //Zero is a special case - // Elvira wants the 8 and tcalc doesn't - mant80final |= (0x8000000000000000); - //Ca-cyber doesn't like this when result is zero. + else if (d != 0){ /* Zero is a special case */ + /* Elvira wants the 8 and tcalc doesn't */ + mant80final |= (0x8000000000000000ll); + /* Ca-cyber doesn't like this when result is zero. */ exp80final += (BIAS80 - BIAS64); } test.begin = (((int16_t)sign80)<<15)| (int16_t)exp80final; test.eind.ll = mant80final; - writememl(easeg,cpu_state.eaaddr,test.eind.ll); + writememl(easeg,cpu_state.eaaddr,test.eind.ll & 0xffffffff); writememl(easeg,cpu_state.eaaddr+4,test.eind.ll>>32); writememw(easeg,cpu_state.eaaddr+8,test.begin); } -static inline void x87_st_fsave(int reg) +static __inline void x87_st_fsave(int reg) { reg = (cpu_state.TOP + reg) & 7; @@ -228,13 +314,14 @@ static inline void x87_st_fsave(int reg) x87_st80(cpu_state.ST[reg]); } -static inline void x87_ld_frstor(int reg) +static __inline void x87_ld_frstor(int reg) { reg = (cpu_state.TOP + reg) & 7; cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr); cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8); +#ifdef USE_NEW_DYNAREC if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64)) { cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; @@ -244,16 +331,25 @@ static inline void x87_ld_frstor(int reg) cpu_state.tag[reg] &= ~TAG_UINT64; cpu_state.ST[reg] = x87_ld80(); } +#else + if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2) + { + cpu_state.tag[reg] = TAG_UINT64; + cpu_state.ST[reg] = (double)cpu_state.MM[reg].q; + } + else + cpu_state.ST[reg] = x87_ld80(); +#endif } -static inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) +static __inline void x87_ldmmx(MMX_REG *r, uint16_t *w4) { r->l[0] = readmeml(easeg, cpu_state.eaaddr); r->l[1] = readmeml(easeg, cpu_state.eaaddr + 4); *w4 = readmemw(easeg, cpu_state.eaaddr + 8); } -static inline void x87_stmmx(MMX_REG r) +static __inline void x87_stmmx(MMX_REG r) { writememl(easeg, cpu_state.eaaddr, r.l[0]); writememl(easeg, cpu_state.eaaddr + 4, r.l[1]); @@ -324,11 +420,12 @@ static __inline uint16_t x87_compare(double a, double b) #endif } -static inline uint16_t x87_ucompare(double a, double b) +static __inline uint16_t x87_ucompare(double a, double b) { #if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__ - uint32_t out; + uint32_t result; +#ifndef _MSC_VER /* Memory barrier, to force GCC to write to the input parameters * before the compare rather than after */ asm volatile ("" : : : "memory"); @@ -339,22 +436,33 @@ static inline uint16_t x87_ucompare(double a, double b) "fclex\n" "fucompp\n" "fnstsw %0\n" - : "=m" (out) + : "=m" (result) : "m" (a), "m" (b) ); +#else + _ReadWriteBarrier(); + _asm + { + fld b + fld a + fclex + fcompp + fnstsw result + } +#endif - return out & (C0|C2|C3); + return result & (C0|C2|C3); #else /* Generic C version is known to give incorrect results in some * situations, eg comparison of infinity (Unreal) */ - uint32_t out = 0; + uint32_t result = 0; if (a == b) - out |= C3; + result |= C3; else if (a < b) - out |= C0; + result |= C0; - return out; + return result; #endif } @@ -386,6 +494,55 @@ typedef union } while (0) #endif +// #ifdef USE_NEW_DYNAREC +#if 1 +#define FP_TAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID; +#define FP_LSTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; +#define FP_LSQ() cpu_state.MM[cpu_state.TOP&7].q = temp64; +#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP&7].q; +#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID; +#ifdef USE_NEW_DYNAREC +#define FP_NNPXC() codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3); +#else +#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); +#endif +#define FP_TOP(x) (x & 7) +#define FP_DTAG 0ULL +#define FP_CTAG 0x0101010101010101ull +#define FP_EMPTY TAG_EMPTY +#ifdef USE_NEW_DYNAREC +#define FP_RNPXC() codegen_set_rounding_mode(X87_ROUNDING_NEAREST); +#else +#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); +#endif +#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; +#define FP_DECTOP() cpu_state.TOP--; +#define FP_INCTOP() cpu_state.TOP++; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) +#define FP_686 +#endif +#else +#define FP_TAG() cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; +#define FP_FTAG() cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; +#define FP_LSTAG() cpu_state.tag[cpu_state.TOP] |= TAG_UINT64; +#define FP_LSQ() cpu_state.MM[cpu_state.TOP].q = temp64; +#define FP_LSRETQ() temp64 = cpu_state.MM[cpu_state.TOP].q; +#define FP_NTAG() cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; +#define FP_NNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); +#define FP_TOP(x) (x) +#define FP_DTAG 0x0303030303030303ll +#define FP_CTAG 0ULL +#define FP_EMPTY 3 +#define FP_RNPXC() cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); +#define FP_ZTAG() cpu_state.tag[cpu_state.TOP&7] = 1; +#define FP_DECTOP() cpu_state.TOP = (cpu_state.TOP - 1) & 7 +#define FP_INCTOP() cpu_state.TOP = (cpu_state.TOP + 1) & 7 +#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#define FP_686 +#endif +#endif + #include "x87_ops_arith.h" #include "x87_ops_misc.h" #include "x87_ops_loadstore.h" @@ -399,10 +556,10 @@ static int op_nofpu_a16(uint32_t fetchdat) return 1; } else - { + { fetch_ea_16(fetchdat); - return 0; - } + return 0; + } } static int op_nofpu_a32(uint32_t fetchdat) { @@ -412,10 +569,10 @@ static int op_nofpu_a32(uint32_t fetchdat) return 1; } else - { + { fetch_ea_32(fetchdat); - return 0; - } + return 0; + } } #endif @@ -434,6 +591,7 @@ static int FPU_ILLEGAL_a16(uint32_t fetchdat) PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); return 0; } + static int FPU_ILLEGAL_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); @@ -748,8 +906,8 @@ const OpFn OP_TABLE(fpu_287_d9_a16)[256] = ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, ILLEGAL_a16, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a16, ILLEGAL_a16, opFTST, opFXAM, ILLEGAL_a16, ILLEGAL_a16, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a16, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, ILLEGAL_a16, opFDECSTP, opFINCSTP, - opFPREM, opFYL2XP1, opFSQRT, ILLEGAL_a16, opFRNDINT, opFSCALE, ILLEGAL_a16, ILLEGAL_a16 + opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a16, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; const OpFn OP_TABLE(fpu_287_d9_a32)[256] = @@ -787,8 +945,8 @@ const OpFn OP_TABLE(fpu_287_d9_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, /*Invalid*/ opFCHS, opFABS, ILLEGAL_a32, ILLEGAL_a32, opFTST, opFXAM, ILLEGAL_a32, ILLEGAL_a32, opFLD1, opFLDL2T, opFLDL2E, opFLDPI, opFLDEG2, opFLDLN2, opFLDZ, ILLEGAL_a32, - opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, ILLEGAL_a32, opFDECSTP, opFINCSTP, - opFPREM, opFYL2XP1, opFSQRT, ILLEGAL_a32, opFRNDINT, opFSCALE, ILLEGAL_a32, ILLEGAL_a32 + opF2XM1, opFYL2X, opFPTAN, opFPATAN, ILLEGAL_a32, opFPREM1, opFDECSTP, opFINCSTP, + opFPREM, opFYL2XP1, opFSQRT, opFSINCOS, opFRNDINT, opFSCALE, opFSIN, opFCOS }; const OpFn OP_TABLE(fpu_d9_a16)[256] = @@ -1023,6 +1181,7 @@ const OpFn OP_TABLE(fpu_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_da_a16)[256] = { opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, @@ -1099,6 +1258,7 @@ const OpFn OP_TABLE(fpu_686_da_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#endif const OpFn OP_TABLE(fpu_287_db_a16)[256] = { @@ -1254,6 +1414,7 @@ const OpFn OP_TABLE(fpu_db_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_db_a16)[256] = { opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, @@ -1330,6 +1491,7 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, opFCOMI, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#endif const OpFn OP_TABLE(fpu_287_dc_a16)[32] = { @@ -1825,6 +1987,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686))) const OpFn OP_TABLE(fpu_686_df_a16)[256] = { opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, @@ -1901,6 +2064,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, opFCOMIP, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, }; +#endif const OpFn OP_TABLE(nofpu_a16)[256] = { diff --git a/src/cpu/x87_ops_arith.h b/src/x87_bak/x87_ops_arith.h similarity index 88% rename from src/cpu/x87_ops_arith.h rename to src/x87_bak/x87_ops_arith.h index 720a5c469..133ecb689 100644 --- a/src/cpu/x87_ops_arith.h +++ b/src/x87_bak/x87_ops_arith.h @@ -11,7 +11,7 @@ static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \ ST(0) += use_var; \ if ((cpu_state.npxc >> 10) & 3) \ fesetround(FE_TONEAREST); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -48,7 +48,7 @@ static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), ST(0), use_var); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -60,7 +60,7 @@ static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ x87_div(ST(0), use_var, ST(0)); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(73); \ return 0; \ } \ @@ -72,7 +72,7 @@ static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) *= use_var; \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(11); \ return 0; \ } \ @@ -84,7 +84,7 @@ static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) -= use_var; \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } \ @@ -96,7 +96,7 @@ static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \ SEG_CHECK_READ(cpu_state.ea_seg); \ load_var = get(); if (cpu_state.abrt) return 1; \ ST(0) = use_var - ST(0); \ - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \ + FP_TAG(); \ CLOCK_CYCLES(8); \ return 0; \ } @@ -128,7 +128,7 @@ static int opFADD(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) + ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -137,7 +137,7 @@ static int opFADDr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -146,7 +146,7 @@ static int opFADDP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -205,7 +205,7 @@ static int opFUCOMPP(uint32_t fetchdat) return 0; } -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#ifdef FP_686 static int opFCOMI(uint32_t fetchdat) { FP_ENTER(); @@ -237,7 +237,7 @@ static int opFDIV(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(0), ST(0), ST(fetchdat & 7)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(73); return 0; } @@ -246,7 +246,7 @@ static int opFDIVr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(73); return 0; } @@ -255,7 +255,7 @@ static int opFDIVP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(73); return 0; @@ -266,7 +266,7 @@ static int opFDIVR(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(0), ST(fetchdat&7), ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(73); return 0; } @@ -275,7 +275,7 @@ static int opFDIVRr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(73); return 0; } @@ -284,7 +284,7 @@ static int opFDIVRP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7)); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(73); return 0; @@ -295,7 +295,7 @@ static int opFMUL(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(16); return 0; } @@ -304,7 +304,7 @@ static int opFMULr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(16); return 0; } @@ -313,7 +313,7 @@ static int opFMULP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(16); return 0; @@ -324,7 +324,7 @@ static int opFSUB(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -333,7 +333,7 @@ static int opFSUBr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -342,7 +342,7 @@ static int opFSUBP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -353,7 +353,7 @@ static int opFSUBR(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = ST(fetchdat & 7) - ST(0); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(8); return 0; } @@ -362,7 +362,7 @@ static int opFSUBRr(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); CLOCK_CYCLES(8); return 0; } @@ -371,7 +371,7 @@ static int opFSUBRP(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7); - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64; + FP_FTAG(); x87_pop(); CLOCK_CYCLES(8); return 0; @@ -399,7 +399,7 @@ static int opFUCOMP(uint32_t fetchdat) return 0; } -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#ifdef FP_686 static int opFUCOMI(uint32_t fetchdat) { FP_ENTER(); diff --git a/src/cpu_new/x87_ops_loadstore.h b/src/x87_bak/x87_ops_loadstore.h similarity index 76% rename from src/cpu_new/x87_ops_loadstore.h rename to src/x87_bak/x87_ops_loadstore.h index 2ed5aec5a..b5ad491f9 100644 --- a/src/cpu_new/x87_ops_loadstore.h +++ b/src/x87_bak/x87_ops_loadstore.h @@ -1,9 +1,27 @@ +/* + * 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. + * + * x87 FPU instructions core. + * + * Version: @(#)x87_ops_loadstore.h 1.0.2 2019/06/11 + * + * Author: Sarah Walker, + * Miran Grca, + * Copyright 2008-2019 Sarah Walker. + * Copyright 2016-2019 Miran Grca. + */ + static int opFILDiw_a16(uint32_t fetchdat) { int16_t temp; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; x87_push((double)temp); CLOCK_CYCLES(13); @@ -15,7 +33,7 @@ static int opFILDiw_a32(uint32_t fetchdat) int16_t temp; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); temp = geteaw(); if (cpu_state.abrt) return 1; x87_push((double)temp); CLOCK_CYCLES(13); @@ -28,10 +46,8 @@ static int opFISTiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); CLOCK_CYCLES(29); return cpu_state.abrt; @@ -42,10 +58,8 @@ static int opFISTiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); CLOCK_CYCLES(29); return cpu_state.abrt; @@ -57,10 +71,8 @@ static int opFISTPiw_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(29); @@ -72,10 +84,8 @@ static int opFISTPiw_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 32767 || temp64 < -32768) - fatal("FISTw overflow %i\n", temp64);*/ seteaw((int16_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(29); @@ -88,11 +98,11 @@ static int opFILDiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); temp64 = geteaq(); if (cpu_state.abrt) return 1; x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP&7].q = temp64; - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; + FP_LSQ(); + FP_LSTAG(); CLOCK_CYCLES(10); return 0; @@ -103,11 +113,11 @@ static int opFILDiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); temp64 = geteaq(); if (cpu_state.abrt) return 1; x87_push((double)temp64); - cpu_state.MM[cpu_state.TOP&7].q = temp64; - cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64; + FP_LSQ(); + FP_LSTAG(); CLOCK_CYCLES(10); return 0; @@ -120,7 +130,7 @@ static int FBSTP_a16(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); tempd = ST(0); if (tempd < 0.0) tempd = -tempd; @@ -147,7 +157,7 @@ static int FBSTP_a32(uint32_t fetchdat) int c; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); tempd = ST(0); if (tempd < 0.0) tempd = -tempd; @@ -174,9 +184,9 @@ static int FISTPiq_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP&7].q; + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) + FP_LSRETQ() else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; @@ -190,9 +200,9 @@ static int FISTPiq_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64) - temp64 = cpu_state.MM[cpu_state.TOP&7].q; + SEG_CHECK_WRITE(cpu_state.ea_seg); + if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64) + FP_LSRETQ() else temp64 = x87_fround(ST(0)); seteaq(temp64); if (cpu_state.abrt) return 1; @@ -207,7 +217,7 @@ static int opFILDil_a16(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); templ = geteal(); if (cpu_state.abrt) return 1; x87_push((double)templ); CLOCK_CYCLES(9); @@ -219,7 +229,7 @@ static int opFILDil_a32(uint32_t fetchdat) int32_t templ; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); templ = geteal(); if (cpu_state.abrt) return 1; x87_push((double)templ); CLOCK_CYCLES(9); @@ -232,10 +242,8 @@ static int opFISTil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 2147483647 || temp64 < -2147483647) - fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); CLOCK_CYCLES(28); return cpu_state.abrt; @@ -246,10 +254,8 @@ static int opFISTil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 2147483647 || temp64 < -2147483647) - fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); CLOCK_CYCLES(28); return cpu_state.abrt; @@ -261,10 +267,8 @@ static int opFISTPil_a16(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 2147483647 || temp64 < -2147483647) - fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(28); @@ -276,10 +280,8 @@ static int opFISTPil_a32(uint32_t fetchdat) int64_t temp64; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); temp64 = x87_fround(ST(0)); -/* if (temp64 > 2147483647 || temp64 < -2147483647) - fatal("FISTl out of range! %i\n", temp64);*/ seteal((int32_t)temp64); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(28); @@ -292,7 +294,7 @@ static int opFLDe_a16(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); t=x87_ld80(); if (cpu_state.abrt) return 1; x87_push(t); CLOCK_CYCLES(6); @@ -304,7 +306,7 @@ static int opFLDe_a32(uint32_t fetchdat) double t; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); t=x87_ld80(); if (cpu_state.abrt) return 1; x87_push(t); CLOCK_CYCLES(6); @@ -316,7 +318,7 @@ static int opFSTPe_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(6); @@ -327,7 +329,7 @@ static int opFSTPe_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); x87_st80(ST(0)); if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(6); @@ -340,7 +342,7 @@ static int opFLDd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); t.i = geteaq(); if (cpu_state.abrt) return 1; x87_push(t.d); CLOCK_CYCLES(3); @@ -352,7 +354,7 @@ static int opFLDd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); t.i = geteaq(); if (cpu_state.abrt) return 1; x87_push(t.d); CLOCK_CYCLES(3); @@ -365,7 +367,7 @@ static int opFSTd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); t.d = ST(0); seteaq(t.i); CLOCK_CYCLES(8); @@ -377,7 +379,7 @@ static int opFSTd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); t.d = ST(0); seteaq(t.i); CLOCK_CYCLES(8); @@ -390,7 +392,7 @@ static int opFSTPd_a16(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -403,7 +405,7 @@ static int opFSTPd_a32(uint32_t fetchdat) x87_td t; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); t.d = ST(0); seteaq(t.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -417,7 +419,7 @@ static int opFLDs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); ts.i = geteal(); if (cpu_state.abrt) return 1; x87_push((double)ts.s); CLOCK_CYCLES(3); @@ -429,7 +431,7 @@ static int opFLDs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); ts.i = geteal(); if (cpu_state.abrt) return 1; x87_push((double)ts.s); CLOCK_CYCLES(3); @@ -442,7 +444,7 @@ static int opFSTs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); ts.s = (float)ST(0); seteal(ts.i); CLOCK_CYCLES(7); @@ -454,7 +456,7 @@ static int opFSTs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); ts.s = (float)ST(0); seteal(ts.i); CLOCK_CYCLES(7); @@ -467,7 +469,7 @@ static int opFSTPs_a16(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); @@ -480,7 +482,7 @@ static int opFSTPs_a32(uint32_t fetchdat) x87_ts ts; FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); ts.s = (float)ST(0); seteal(ts.i); if (cpu_state.abrt) return 1; x87_pop(); diff --git a/src/cpu/x87_ops_misc.h b/src/x87_bak/x87_ops_misc.h similarity index 88% rename from src/cpu/x87_ops_misc.h rename to src/x87_bak/x87_ops_misc.h index 36dbd8a76..406c6c86d 100644 --- a/src/cpu/x87_ops_misc.h +++ b/src/x87_bak/x87_ops_misc.h @@ -21,7 +21,6 @@ static int opFSTSW_AX(uint32_t fetchdat) #endif - static int opFNOP(uint32_t fetchdat) { FP_ENTER(); @@ -49,10 +48,10 @@ static int opFINIT(uint32_t fetchdat) #else cpu_state.npxc = 0x37F; #endif - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + FP_RNPXC(); cpu_state.npxs = 0; p = (uint64_t *)cpu_state.tag; - *p = 0x0303030303030303ll; + *p = FP_DTAG; cpu_state.TOP = 0; cpu_state.ismmx = 0; CLOCK_CYCLES(17); @@ -65,7 +64,7 @@ static int opFFREE(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; CLOCK_CYCLES(3); return 0; } @@ -74,7 +73,7 @@ static int opFFREEP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3; if (cpu_state.abrt) return 1; + cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; if (cpu_state.abrt) return 1; x87_pop(); CLOCK_CYCLES(3); return 0; @@ -113,7 +112,7 @@ static int FSTOR() case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -122,7 +121,7 @@ static int FSTOR() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -144,7 +143,7 @@ static int FSTOR() 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.TOP && (*p == FP_CTAG)) cpu_state.ismmx = 1; CLOCK_CYCLES((cr0 & 1) ? 34 : 44); @@ -154,7 +153,7 @@ static int opFSTOR_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -163,7 +162,7 @@ static int opFSTOR_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_READ(cpu_state.ea_seg); + SEG_CHECK_READ(cpu_state.ea_seg); FSTOR(); return cpu_state.abrt; } @@ -174,7 +173,7 @@ static int FSAVE() uint64_t *p; FP_ENTER(); - cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (cpu_state.TOP << 11); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (FP_TOP(cpu_state.TOP) << 11); switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { @@ -306,10 +305,10 @@ static int FSAVE() } cpu_state.npxc = 0x37F; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + FP_RNPXC(); cpu_state.npxs = 0; p = (uint64_t *)cpu_state.tag; - *p = 0x0303030303030303ll; + *p = FP_DTAG; cpu_state.TOP = 0; cpu_state.ismmx = 0; @@ -320,7 +319,7 @@ static int opFSAVE_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -329,7 +328,7 @@ static int opFSAVE_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); + SEG_CHECK_WRITE(cpu_state.ea_seg); FSAVE(); return cpu_state.abrt; } @@ -339,8 +338,8 @@ static int opFSTSW_a16(uint32_t fetchdat) { FP_ENTER(); fetch_ea_16(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -349,8 +348,8 @@ static int opFSTSW_a32(uint32_t fetchdat) { FP_ENTER(); fetch_ea_32(fetchdat); - SEG_CHECK_WRITE(cpu_state.ea_seg); - seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11)); + SEG_CHECK_WRITE(cpu_state.ea_seg); + seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11)); CLOCK_CYCLES(3); return cpu_state.abrt; } @@ -367,8 +366,8 @@ static int opFLD(uint32_t fetchdat) old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; x87_push(ST(fetchdat&7)); - cpu_state.tag[cpu_state.TOP] = old_tag; - cpu_state.MM[cpu_state.TOP].q = old_i64; + cpu_state.tag[FP_TOP(cpu_state.TOP)] = old_tag; + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = old_i64; CLOCK_CYCLES(4); return 0; } @@ -383,11 +382,11 @@ static int opFXCH(uint32_t fetchdat) td = ST(0); ST(0) = ST(fetchdat&7); ST(fetchdat&7) = td; - old_tag = cpu_state.tag[cpu_state.TOP]; - cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; + old_tag = cpu_state.tag[FP_TOP(cpu_state.TOP)]; + cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag; - old_i64 = cpu_state.MM[cpu_state.TOP].q; - cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; + old_i64 = cpu_state.MM[FP_TOP(cpu_state.TOP)].q; + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64; CLOCK_CYCLES(4); @@ -399,7 +398,7 @@ static int opFCHS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = -ST(0); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(6); return 0; } @@ -409,7 +408,7 @@ static int opFABS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = fabs(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(3); return 0; } @@ -430,7 +429,7 @@ static int opFXAM(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; cpu_state.npxs &= ~(C0|C1|C2|C3); - if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3); + if (cpu_state.tag[cpu_state.TOP&7] == FP_EMPTY) cpu_state.npxs |= (C0|C3); else if (ST(0) == 0.0) cpu_state.npxs |= C3; else cpu_state.npxs |= C2; if (ST(0) < 0.0) cpu_state.npxs |= C1; @@ -497,7 +496,7 @@ static int opFLDZ(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; x87_push(0.0); - cpu_state.tag[cpu_state.TOP&7] = 1; + FP_ZTAG(); CLOCK_CYCLES(4); return 0; } @@ -507,7 +506,7 @@ static int opF2XM1(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = pow(2.0, ST(0)) - 1.0; - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(200); return 0; } @@ -517,7 +516,7 @@ static int opFYL2X(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(1) = ST(1) * (log(ST(0)) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -527,8 +526,8 @@ static int opFYL2XP1(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - ST(1) = ST(1) * (log1p(ST(0)) / log(2.0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0)); + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -539,7 +538,7 @@ static int opFPTAN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = tan(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); x87_push(1.0); cpu_state.npxs &= ~C2; CLOCK_CYCLES(235); @@ -551,7 +550,7 @@ static int opFPATAN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(1) = atan2(ST(1), ST(0)); - cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64; + FP_NTAG(); x87_pop(); CLOCK_CYCLES(250); return 0; @@ -561,7 +560,7 @@ static int opFDECSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.TOP = (cpu_state.TOP - 1) & 7; + FP_DECTOP(); CLOCK_CYCLES(4); return 0; } @@ -570,7 +569,7 @@ static int opFINCSTP(uint32_t fetchdat) { FP_ENTER(); cpu_state.pc++; - cpu_state.TOP = (cpu_state.TOP + 1) & 7; + FP_INCTOP(); CLOCK_CYCLES(4); return 0; } @@ -582,7 +581,7 @@ static int opFPREM(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -598,7 +597,7 @@ static int opFPREM1(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)(ST(0) / ST(1)); ST(0) = ST(0) - (ST(1) * (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); cpu_state.npxs &= ~(C0|C1|C2|C3); if (temp64 & 4) cpu_state.npxs|=C0; if (temp64 & 2) cpu_state.npxs|=C3; @@ -613,7 +612,7 @@ static int opFSQRT(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = sqrt(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(83); return 0; } @@ -626,7 +625,7 @@ static int opFSINCOS(uint32_t fetchdat) cpu_state.pc++; td = ST(0); ST(0) = sin(td); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); x87_push(cos(td)); cpu_state.npxs &= ~C2; CLOCK_CYCLES(330); @@ -636,10 +635,18 @@ static int opFSINCOS(uint32_t fetchdat) static int opFRNDINT(uint32_t fetchdat) { + double rounded; FP_ENTER(); cpu_state.pc++; - ST(0) = (double)x87_fround(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + rounded = (double) x87_fround(ST(0)); +#ifndef PCEM_CODE + if (rounded > ST(0)) + cpu_state.npxs |= C1; + else + cpu_state.npxs &= ~C1; +#endif + ST(0) = rounded; + FP_TAG(); CLOCK_CYCLES(21); return 0; } @@ -651,7 +658,7 @@ static int opFSCALE(uint32_t fetchdat) cpu_state.pc++; temp64 = (int64_t)ST(1); ST(0) = ST(0) * pow(2.0, (double)temp64); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); CLOCK_CYCLES(30); return 0; } @@ -662,7 +669,7 @@ static int opFSIN(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = sin(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -673,7 +680,7 @@ static int opFCOS(uint32_t fetchdat) FP_ENTER(); cpu_state.pc++; ST(0) = cos(ST(0)); - cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; + FP_TAG(); cpu_state.npxs &= ~C2; CLOCK_CYCLES(300); return 0; @@ -689,7 +696,7 @@ static int FLDENV() case 0x000: /*16-bit real mode*/ case 0x001: /*16-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2); x87_settag(readmemw(easeg, cpu_state.eaaddr+4)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -697,7 +704,7 @@ static int FLDENV() case 0x100: /*32-bit real mode*/ case 0x101: /*32-bit protected mode*/ cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr); - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4); x87_settag(readmemw(easeg, cpu_state.eaaddr+8)); cpu_state.TOP = (cpu_state.npxs >> 11) & 7; @@ -735,7 +742,7 @@ static int opFLDCW_a16(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); CLOCK_CYCLES(4); return 0; } @@ -749,7 +756,7 @@ static int opFLDCW_a32(uint32_t fetchdat) tempw = geteaw(); if (cpu_state.abrt) return 1; cpu_state.npxc = tempw; - cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); + FP_NNPXC(); CLOCK_CYCLES(4); return 0; } @@ -839,7 +846,7 @@ static int opFSTCW_a32(uint32_t fetchdat) #endif #ifndef FPU_8087 -#if defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)) +#ifdef FP_686 #define opFCMOV(condition) \ static int opFCMOV ## condition(uint32_t fetchdat) \ { \ @@ -847,8 +854,8 @@ static int opFSTCW_a32(uint32_t fetchdat) cpu_state.pc++; \ if (cond_ ## condition) \ { \ - cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ - cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ + cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \ + cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \ ST(0) = ST(fetchdat & 7); \ } \ CLOCK_CYCLES(4); \