Merge pull request #621 from 86Box/temp

Temp
This commit is contained in:
OBattler
2020-03-24 22:48:55 +01:00
committed by GitHub
583 changed files with 33694 additions and 10165 deletions

1
.gitignore vendored
View File

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

3
src/386.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\386.c and CPU_NEW\386.C
FC: no differences encountered

3
src/386_common.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\386_common.h and CPU_NEW\386_COMMON.H
FC: no differences encountered

3
src/386_dynarec.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\386_dynarec.c and CPU_NEW\386_DYNAREC.C
FC: no differences encountered

3
src/386_dynarec_ops.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\386_dynarec_ops.c and CPU_NEW\386_DYNAREC_OPS.C
FC: no differences encountered

3
src/386_ops.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\x86_ops.h and CPU_NEW\X86_OPS.H
FC: no differences encountered

205
src/808x.txt Normal file
View File

@@ -0,0 +1,205 @@
Comparing files CPU\808x.c and CPU_NEW\808X.C
***** CPU\808x.c
*
* Version: @(#)808x.c 1.0.11 2019/10/21
*
***** CPU_NEW\808X.C
*
* Version: @(#)808x.c 1.0.9 2019/02/13
*
*****
***** CPU\808x.c
#include <wchar.h>
#define HAVE_STDARG_H
***** CPU_NEW\808X.C
#include <wchar.h>
#define HAVE_STDARG_H
*****
***** CPU\808x.c
int nmi = 0, nmi_auto_clear = 0;
int nmi_enable = 1;
***** CPU_NEW\808X.C
int nmi = 0, nmi_auto_clear = 0;
*****
***** CPU\808x.c
/* 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
***** CPU_NEW\808X.C
/* 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
*****
***** CPU\808x.c
pfq_add(c, !bus);
if (bus < 2) {
// clock_end();
// clock_start();
}
}
***** CPU_NEW\808X.C
pfq_add(c, !bus);
clock_end();
clock_start();
}
*****
***** CPU\808x.c
{
if (c <= 0)
return;
cycles -= c;
***** CPU_NEW\808X.C
{
cycles -= c;
*****
***** CPU\808x.c
if (!is286)
fetch_and_bus(c, 2);
}
***** CPU_NEW\808X.C
if (!is286)
fetch_and_bus(c, 1);
}
*****
***** CPU\808x.c
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. */
***** CPU_NEW\808X.C
/* Fetches the effective address from the prefetch queue according to MOD and R/M. */
*****
***** CPU\808x.c
cpu_state.pc = 0xFFF0;
cpu_state.seg_cs.base = 0xFFFF0000;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
***** CPU_NEW\808X.C
cpu_state.pc = 0xFFF0;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
*****
***** CPU\808x.c
resetmcr();
cpu_set_edx();
***** CPU_NEW\808X.C
resetmcr();
pfq_clear();
cpu_set_edx();
*****
***** CPU\808x.c
#endif
if (!hard)
flushmmucache();
x86_was_reset = 1;
***** CPU_NEW\808X.C
#endif
if (!hard)
flushmmucache();
x86_was_reset = 1;
*****
***** CPU\808x.c
pfq_clear();
prefetching = 1;
takeint = 0;
***** CPU_NEW\808X.C
prefetching = 1;
takeint = 0;
*****
***** CPU\808x.c
cpu_ven_reset();
cpu_alu_op = 0;
}
***** CPU_NEW\808X.C
cpu_ven_reset();
}
*****
***** CPU\808x.c
/* This has to be done so that the special case of ADD does not kick in. */
size_mask = (1 << bit_count) - 1;
***** CPU_NEW\808X.C
size_mask = (1 << bit_count) - 1;
*****
***** CPU\808x.c
uint16_t new_cs, new_ip;
uint32_t result;
int bits;
***** CPU_NEW\808X.C
uint16_t new_cs, new_ip;
int bits;
*****
***** CPU\808x.c
if (opcode & 1) {
result = cpu_data;
mul(AX, cpu_data);
***** CPU_NEW\808X.C
if (opcode & 1) {
mul(AX, cpu_data);
*****
***** CPU\808x.c
cpu_data |= DX;
result = ((uint32_t) DX << 16) | AX;
if ((rmdat & 0x38) == 0x20)
set_co_mul(DX != 0x0000);
else
set_co_mul(result != sign_extend32(AX));
} else {
***** CPU_NEW\808X.C
cpu_data |= DX;
set_co_mul(DX != ((AX & 0x8000) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xffff));
} else {
*****
***** CPU\808x.c
cpu_data |= AH;
if ((rmdat & 0x38) == 0x20)
set_co_mul(AH != 0x00);
else
set_co_mul(AX != sign_extend(AL));
}
***** CPU_NEW\808X.C
cpu_data |= AH;
set_co_mul(AH != ((AL & 0x80) == 0 || (rmdat & 0x38) == 0x20 ? 0 : 0xff));
}
*****
***** CPU\808x.c
noint = 0;
cpu_alu_op = 0;
}
***** CPU_NEW\808X.C
noint = 0;
}
*****

View File

@@ -99,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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -29,10 +29,10 @@
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../config.h"
#include "../plat.h"
#include "../scsi/scsi_device.h"
#include "86box.h"
#include "config.h"
#include "plat.h"
#include "scsi_device.h"
#include "cdrom_image_backend.h"
#include "cdrom.h"
#include "cdrom_image.h"

View File

@@ -35,8 +35,8 @@
#endif
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "../plat.h"
#include "86box.h"
#include "plat.h"
#include "cdrom_image_backend.h"
@@ -190,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;
}
@@ -209,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. */

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated chipsets.
*
* Version: @(#)machine.h 1.0.1 2020/01/14
* Version: @(#)machine.h 1.0.2 2020/01/24
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
@@ -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;

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -24,15 +24,15 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../keyboard.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "86box.h"
#include "device.h"
#include "timer.h"
#include "fdd.h"
#include "fdc.h"
#include "keyboard.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "chipset.h"
#define NEAT_DEBUG 0

View File

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

View File

@@ -13,7 +13,7 @@
* 8MB of DRAM chips', because it works fine with bus-based
* memory expansion.
*
* Version: @(#)scamp.c 1.0.0 2020/01/21
* Version: @(#)scamp.c 1.0.1 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
*
@@ -24,16 +24,21 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../cpu/cpu.h"
#include "../timer.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../port_92.h"
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "device.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "port_92.h"
#include "chipset.h"
typedef struct {
void *parent;
int bank;
} ram_struct_t;
typedef struct {
int cfg_index;
uint8_t cfg_regs[256];
@@ -42,6 +47,9 @@ typedef struct {
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];
@@ -129,8 +137,9 @@ static const struct
static uint8_t
ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -156,8 +165,9 @@ ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv)
static void
ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -186,8 +196,9 @@ ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv)
static uint8_t
ram_mirrored_interleaved_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -213,8 +224,9 @@ ram_mirrored_interleaved_read(uint32_t addr, void *priv)
static void
ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -242,8 +254,9 @@ ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv)
static uint8_t
ram_mirrored_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -257,8 +270,9 @@ ram_mirrored_read(uint32_t addr, void *priv)
static void
ram_mirrored_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)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];
@@ -674,14 +688,19 @@ scamp_init(const device_t *info)
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 *)c);
&ram[addr], MEM_MAPPING_INTERNAL, (void *) &dev->ram_struct[c]);
mem_mapping_disable(&dev->ram_mapping[c]);
dev->ram_phys_base[c] = addr;

View File

@@ -23,24 +23,19 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../device.h"
#ifdef USE_NEW_DYNAREC
#include "../cpu_new/cpu.h"
#include "../cpu_new/x86.h"
#else
#include "../cpu/cpu.h"
#include "../cpu/x86.h"
#endif
#include "../timer.h"
#include "../floppy/fdd.h"
#include "../floppy/fdc.h"
#include "../keyboard.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../port_92.h"
#include "../rom.h"
#include "86box.h"
#include "device.h"
#include "cpu.h"
#include "x86.h"
#include "timer.h"
#include "fdd.h"
#include "fdc.h"
#include "keyboard.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "port_92.h"
#include "rom.h"
#include "chipset.h"

View File

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

View File

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

View File

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

View File

@@ -21,13 +21,13 @@
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "../mem.h"
#include "../io.h"
#include "../rom.h"
#include "../pci.h"
#include "../device.h"
#include "../keyboard.h"
#include "86box.h"
#include "mem.h"
#include "86box_io.h"
#include "rom.h"
#include "pci.h"
#include "device.h"
#include "keyboard.h"
#include "chipset.h"
@@ -292,7 +292,7 @@ via_mvp3_init(const device_t *info)
{
via_mvp3_t *dev = (via_mvp3_t *) malloc(sizeof(via_mvp3_t));
pci_add_card(0, via_mvp3_read, via_mvp3_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, via_mvp3_read, via_mvp3_write, dev);
via_mvp3_setup(dev);

View File

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

View File

@@ -34,7 +34,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include "86box.h"
#include "cpu/cpu.h"
#include "cpu.h"
#include "device.h"
#include "timer.h"
#include "nvr.h"
@@ -42,24 +42,23 @@
#include "isamem.h"
#include "isartc.h"
#include "lpt.h"
#include "disk/hdd.h"
#include "disk/hdc.h"
#include "disk/hdc_ide.h"
#include "floppy/fdd.h"
#include "floppy/fdc.h"
#include "game/gameport.h"
#include "machine/machine.h"
#include "hdd.h"
#include "hdc.h"
#include "hdc_ide.h"
#include "fdd.h"
#include "fdc.h"
#include "gameport.h"
#include "machine.h"
#include "mouse.h"
#include "network/network.h"
#include "scsi/scsi.h"
#include "scsi/scsi_device.h"
#include "cdrom/cdrom.h"
#include "disk/zip.h"
#include "sound/sound.h"
#include "sound/midi.h"
#include "sound/snd_mpu401.h"
#include "sound/sound.h"
#include "video/video.h"
#include "network.h"
#include "scsi.h"
#include "scsi_device.h"
#include "cdrom.h"
#include "zip.h"
#include "sound.h"
#include "midi.h"
#include "snd_mpu401.h"
#include "video.h"
#include "plat.h"
#include "plat_midi.h"
#include "ui.h"
@@ -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) - 1);
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) - 1);
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));
@@ -807,6 +806,7 @@ load_other_peripherals(void)
ide_qua_enabled = !!config_get_int(cat, "ide_qua", 0);
bugger_enabled = !!config_get_int(cat, "bugger_enabled", 0);
postcard_enabled = !!config_get_int(cat, "postcard_enabled", 0);
for (c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
@@ -1687,6 +1687,11 @@ save_other_peripherals(void)
else
config_set_int(cat, "bugger_enabled", bugger_enabled);
if (postcard_enabled == 0)
config_delete_var(cat, "postcard_enabled");
else
config_set_int(cat, "postcard_enabled", postcard_enabled);
for (c = 0; c < ISAMEM_MAX; c++) {
sprintf(temp, "isamem%d_type", c);
if (isamem_type[c] == 0)

3
src/cpu.txt Normal file
View File

@@ -0,0 +1,3 @@
Comparing files CPU\cpu.c and CPU_NEW\CPU.C
FC: no differences encountered

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -24,13 +24,13 @@
#include <stdarg.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../device.h"
#include "../timer.h"
#include "../machine/machine.h"
#include "../mem.h"
#include "../nvr.h"
#include "device.h"
#include "timer.h"
#include "machine.h"
#include "mem.h"
#include "nvr.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
@@ -108,8 +108,8 @@ static void seg_reset(x86seg *s)
if(s == &cpu_state.seg_cs)
{
// TODO - When the PC is reset, initialization of the CS descriptor must be like the annotated line below.
//s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0;
s->base = AT ? 0xF0000 : 0xFFFF0;
s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0;
// s->base = AT ? 0xF0000 : 0xFFFF0;
s->seg = AT ? 0xF000 : 0xFFFF;
}
else

View File

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

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

@@ -0,0 +1,335 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
# define INFINITY (__builtin_inff())
#endif
#define HAVE_STDARG_H
#include "86box.h"
#include "cpu.h"
#include "timer.h"
#include "x86.h"
#include "x87.h"
#include "nmi.h"
#include "mem.h"
#include "pic.h"
#include "pit.h"
#include "fdd.h"
#include "fdc.h"
#include "386_common.h"
#ifdef USE_NEW_DYNAREC
#include "codegen.h"
#endif
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
extern int codegen_flags_changed;
int tempc, oldcpl, optype, inttype, oddeven = 0;
int timetolive;
uint16_t oldcs;
uint32_t oldds, oldss, olddslimit, oldsslimit,
olddslimitw, oldsslimitw;
uint32_t oxpc;
uint32_t rmdat32;
uint32_t backupregs[16];
x86seg _oldds;
#ifdef ENABLE_386_LOG
int x386_do_log = ENABLE_386_LOG;
void
x386_log(const char *fmt, ...)
{
va_list ap;
if (x386_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define x386_log(fmt, ...)
#endif
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (cpu_rm == 4)
{
uint8_t sib = rmdat >> 8;
switch (cpu_mod)
{
case 0:
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
cpu_state.pc++;
break;
case 1:
cpu_state.pc++;
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
// pc++;
break;
case 2:
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
cpu_state.pc += 5;
break;
}
/*SIB byte present*/
if ((sib & 7) == 5 && !cpu_mod)
cpu_state.eaaddr = getlong();
else if ((sib & 6) == 4 && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
}
else
{
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
if (cpu_mod)
{
if (cpu_rm == 5 && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1)
{
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
cpu_state.pc++;
}
else
{
cpu_state.eaaddr += getlong();
}
}
else if (cpu_rm == 5)
{
cpu_state.eaaddr = getlong();
}
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
if (!cpu_mod && cpu_rm == 6)
{
cpu_state.eaaddr = getword();
}
else
{
switch (cpu_mod)
{
case 0:
cpu_state.eaaddr = 0;
break;
case 1:
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
break;
case 2:
cpu_state.eaaddr = getword();
break;
}
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
{
easeg = ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 0; }
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 0
#include "x86_flags.h"
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "x86_ops.h"
void
exec386(int cycs)
{
// uint8_t opcode;
int vector, tempi, cycdiff, oldcyc;
int cycle_period, ins_cycles;
uint32_t addr;
cycles += cycs;
while (cycles > 0) {
cycle_period = (timer_target - (uint32_t)tsc) + 1;
x86_was_reset = 0;
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
oldcs=CS;
oldcpl=CPL;
#endif
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
#ifndef USE_NEW_DYNAREC
x86_was_reset = 0;
#endif
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt) {
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
#ifndef USE_NEW_DYNAREC
if (!use32) cpu_state.pc &= 0xffff;
#endif
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
#ifndef USE_NEW_DYNAREC
CS = oldcs;
#endif
cpu_state.pc = cpu_state.oldpc;
x386_log("Double fault %i\n", ins);
pmodeint(8, 0);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_LOG
x386_log("Triple fault - reset\n");
#endif
}
}
}
ins_cycles -= cycles;
tsc += ins_cycles;
cycdiff = oldcyc - cycles;
if (trap) {
flags_rebuild();
if (msw&1)
pmodeint(1,0);
else {
writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags);
writememw(ss, (SP - 4) & 0xFFFF, CS);
writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
SP -= 6;
addr = (1 << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = readmemw(0, addr);
loadcs(readmemw(0, addr + 2));
}
} else if (nmi && nmi_enable && nmi_mask) {
cpu_state.oldpc = cpu_state.pc;
x86_int(2);
nmi_enable = 0;
if (nmi_auto_clear) {
nmi_auto_clear = 0;
nmi = 0;
}
} else if ((cpu_state.flags & I_FLAG) && pic_intpending) {
vector = picinterrupt();
if (vector != -1) {
flags_rebuild();
if (msw & 1)
pmodeint(vector, 0);
else {
writememw(ss, (SP - 2) & 0xFFFF, cpu_state.flags);
writememw(ss, (SP - 4) & 0xFFFF, CS);
writememw(ss, (SP - 6) & 0xFFFF, cpu_state.pc);
SP -= 6;
addr = (vector << 2) + idt.base;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = readmemw(0, addr);
loadcs(readmemw(0, addr + 2));
}
}
}
ins++;
if (timetolive) {
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process();
}
}
}

View File

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

View File

@@ -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;
@@ -1134,10 +900,10 @@ inrecomp=0;
}
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
cycles_main -= (cycles_start - cycles);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,18 +9,18 @@
# 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"
#include "codegen_backend.h"
@@ -874,10 +874,11 @@ void exec386_dynarec(int cycs)
}
}
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
cycles_main -= (cycles_start - cycles);
}
}

View File

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

View File

@@ -9,15 +9,14 @@
#endif
#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 "../pic.h"
#include "86box_io.h"
#include "mem.h"
#include "nmi.h"
#include "pic.h"
#include "codegen.h"
#define CPU_BLOCK_END() cpu_block_end = 1

View File

@@ -167,7 +167,7 @@ static int ILLEGAL(uint32_t fetchdat)
return 0;
}
#if defined(DEV_BRANCH) && (defined(USE_AMD_K) || defined(USE_I686))
#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;
@@ -184,13 +184,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#endif
#endif
#include "x86seg.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"
@@ -220,10 +218,16 @@ 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 "x86seg.h"
#include "x86_ops_call.h"
#include "x86_ops_shift.h"
#ifdef USE_NEW_DYNAREC
#include "x86_ops_amd.h"
#include "x86_ops_3dnow.h"
#endif
static int op0F_w_a16(uint32_t fetchdat)
@@ -454,7 +458,7 @@ 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,
/*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,
@@ -632,6 +636,99 @@ const OpFn OP_TABLE(winchip_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(winchip2_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, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*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,opMOV_TRx_r_a16,ILLEGAL, 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, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*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,opMOV_TRx_r_a16,ILLEGAL, 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, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*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,opMOV_TRx_r_a32,ILLEGAL, 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, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*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,opMOV_TRx_r_a32,ILLEGAL, 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,
};
#endif
const OpFn OP_TABLE(pentium_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
@@ -814,7 +911,191 @@ 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,
};
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
#ifdef USE_NEW_DYNAREC
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,
};
const OpFn OP_TABLE(k62_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, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*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, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*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, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*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, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*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(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
const OpFn OP_TABLE(c6x86mx_0f)[1024] =
{
/*16-bit data, 16-bit addr*/

View File

@@ -9,7 +9,7 @@
* 808x CPU emulation, mostly ported from reenigne's XTCE, which
* is cycle-accurate.
*
* Version: @(#)808x.c 1.0.9 2019/02/13
* Version: @(#)808x.c 1.0.11 2019/10/21
*
* Authors: Andrew Jenner, <https://www.reenigne.org>
* Miran Grca, <mgrca8@gmail.com>
@@ -23,17 +23,18 @@
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "x86.h"
#include "../machine/machine.h"
#include "../io.h"
#include "../mem.h"
#include "../rom.h"
#include "../nmi.h"
#include "../pic.h"
#include "../timer.h"
#include "machine.h"
#include "86box_io.h"
#include "mem.h"
#include "rom.h"
#include "nmi.h"
#include "pic.h"
#include "timer.h"
/* The opcode of the instruction currently being executed. */
uint8_t opcode;
@@ -235,7 +236,7 @@ clock_end(void)
{
int diff = cycdiff - cycles;
/* On 808x systems, clock speed is usually crystal frequency divided by an integer. */
/* 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();
@@ -257,8 +258,10 @@ fetch_and_bus(int c, int bus)
}
pfq_add(c, !bus);
clock_end();
clock_start();
if (bus < 2) {
clock_end();
clock_start();
}
}
@@ -275,10 +278,13 @@ wait(int c, int bus)
void
sub_cycles(int c)
{
if (c <= 0)
return;
cycles -= c;
if (!is286)
fetch_and_bus(c, 1);
fetch_and_bus(c, 2);
}
@@ -647,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)
@@ -912,7 +925,7 @@ reset_common(int hard)
if (isibmcpu)
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
cpu_state.eflags = 0;
@@ -920,6 +933,7 @@ reset_common(int hard)
if (AT) {
loadcs(0xF000);
cpu_state.pc = 0xFFF0;
cpu_state.seg_cs.base = 0xFFFF0000;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
} else {
loadcs(0xFFFF);
@@ -950,8 +964,8 @@ reset_common(int hard)
if (hard)
codegen_reset();
#endif
if (!hard)
flushmmucache();
if (!hard)
flushmmucache();
x86_was_reset = 1;
cpu_alt_reset = 0;
@@ -959,6 +973,8 @@ reset_common(int hard)
takeint = 0;
cpu_ven_reset();
cpu_alu_op = 0;
}
@@ -1754,6 +1770,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;
@@ -2736,17 +2753,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. */
@@ -2881,6 +2906,8 @@ execx86(int cycs)
if (noint)
noint = 0;
cpu_alu_op = 0;
}
ins++;

View File

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

View File

@@ -42,16 +42,16 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#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
@@ -75,11 +75,13 @@ enum {
CPUID_FXSR = (1 << 24)
};
#ifdef USE_NEW_DYNAREC
/*Addition flags returned by CPUID function 0x80000001*/
enum
{
CPUID_3DNOW = (1 << 31)
};
#endif
#ifdef USE_DYNAREC
@@ -103,8 +105,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;
@@ -126,7 +130,9 @@ const OpFn *x86_opcodes_df_a16;
const OpFn *x86_opcodes_df_a32;
const OpFn *x86_opcodes_REPE;
const OpFn *x86_opcodes_REPNE;
#ifdef USE_NEW_DYNAREC
const OpFn *x86_opcodes_3DNOW;
#endif
int in_smm = 0, smi_line = 0, smi_latched = 0;
uint32_t smbase = 0x30000;
@@ -195,13 +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. */
#ifdef USE_NEW_DYNAREC
uint64_t star = 0; /* AMD K6-2+. */
#endif
uint64_t amd_efer = 0, amd_whcr = 0, /* AMD K6-2+ registers. */
amd_uwccr = 0, amd_epmr = 0,
#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;
@@ -257,7 +271,7 @@ cpu_set(void)
cpu_manufacturer = 0;
cpu = 0;
}
cpu_effective = cpu;
cpu_s = &machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective];
@@ -272,8 +286,14 @@ cpu_set(void)
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(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;
}
@@ -315,7 +335,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,12 +343,16 @@ cpu_set(void)
#endif
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
#ifdef USE_NEW_DYNAREC
x86_opcodes_3DNOW = ops_3DNOW;
#endif
#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)
@@ -490,7 +514,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*/
@@ -553,7 +577,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);
@@ -590,6 +614,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);
@@ -941,6 +966,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);
@@ -982,6 +1008,7 @@ cpu_set(void)
cpu_cyrix_alignment = 1;
codegen_timing_set(&codegen_timing_winchip2);
break;
#endif
case CPU_PENTIUM:
#ifdef USE_DYNAREC
@@ -1069,6 +1096,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);
@@ -1237,13 +1265,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*/
@@ -1277,7 +1307,7 @@ 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;
@@ -1321,10 +1351,16 @@ 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:
@@ -1369,6 +1405,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:
@@ -1422,7 +1459,11 @@ 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_686);
#endif
#endif
break;
@@ -1478,7 +1519,11 @@ 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_686);
#endif
#endif
break;
#endif
@@ -1534,7 +1579,11 @@ 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 | 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
@@ -1667,6 +1716,7 @@ cpu_CPUID(void)
EAX = EBX = ECX = EDX = 0;
break;
#ifdef USE_NEW_DYNAREC
case CPU_WINCHIP2:
switch (EAX)
{
@@ -1726,6 +1776,7 @@ cpu_CPUID(void)
break;
}
break;
#endif
case CPU_PENTIUM:
if (!EAX)
@@ -1745,6 +1796,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)
{
@@ -1876,7 +1928,9 @@ 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)
@@ -2037,6 +2091,7 @@ cpu_CPUID(void)
break;
}
break;
#endif
case CPU_PENTIUMMMX:
if (!EAX)
@@ -2057,6 +2112,7 @@ cpu_CPUID(void)
break;
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
case CPU_Cx6x86:
if (!EAX)
{
@@ -2132,6 +2188,7 @@ cpu_CPUID(void)
else
EAX = EBX = ECX = EDX = 0;
break;
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
@@ -2211,6 +2268,7 @@ cpu_CPUID(void)
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:
@@ -2222,6 +2280,7 @@ void cpu_ven_reset(void)
amd_efer = amd_whcr = 0ULL;
star = 0ULL;
break;
#ifdef USE_NEW_DYNAREC
case CPU_K6_2C:
amd_efer = 2ULL;
amd_whcr = star = 0ULL;
@@ -2244,7 +2303,9 @@ void cpu_ven_reset(void)
amd_pfir = amd_l2aar = 0ULL;
amd_epmr = 0ULL;
break;
#endif
}
#endif
}
void cpu_RDMSR()
@@ -2252,7 +2313,9 @@ 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)
{
@@ -2282,6 +2345,7 @@ void cpu_RDMSR()
}
break;
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K))
case CPU_K5:
case CPU_5K86:
case CPU_K6:
@@ -2312,7 +2376,9 @@ void cpu_RDMSR()
break;
}
break;
#endif
#ifdef USE_NEW_DYNAREC
case CPU_K6_2:
EAX = EDX = 0;
switch (ECX)
@@ -2493,6 +2559,7 @@ void cpu_RDMSR()
break;
}
break;
#endif
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
@@ -2505,6 +2572,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:
@@ -2517,6 +2585,7 @@ void cpu_RDMSR()
break;
}
break;
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
@@ -2649,12 +2718,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:
@@ -2679,10 +2752,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
@@ -2697,6 +2772,7 @@ void cpu_WRMSR()
}
break;
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K))
case CPU_K5:
case CPU_5K86:
case CPU_K6:
@@ -2726,7 +2802,9 @@ void cpu_WRMSR()
break;
}
break;
#endif
#ifdef USE_NEW_DYNAREC
case CPU_K6_2:
switch (ECX)
{
@@ -2887,6 +2965,7 @@ void cpu_WRMSR()
break;
}
break;
#endif
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
@@ -2897,6 +2976,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:
@@ -2908,6 +2988,7 @@ void cpu_WRMSR()
break;
}
break;
#endif
#ifdef DEV_BRANCH
#ifdef USE_I686
@@ -3040,6 +3121,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)
@@ -3047,6 +3129,7 @@ static void cpu_write(uint16_t addr, uint8_t val, void *priv)
else
CPUID = 0;
}
#endif
}
break;
case 0xe9: /*CCR5*/

View File

@@ -18,63 +18,72 @@
* 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_i486DX,
CPU_Am486DX,
CPU_Cx486DX,
CPU_iDX4,
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
#if defined(DEV_BRANCH) && defined(USE_I686)
CPU_PENTIUMPRO, /* 686 class CPUs */
#ifdef USE_PENTIUM2
CPU_PENTIUM2,
#endif
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
@@ -96,6 +105,7 @@ typedef struct {
int8_t atclk_div;
} CPU;
extern CPU cpus_8088[];
extern CPU cpus_8086[];
extern CPU cpus_286[];
@@ -115,30 +125,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
#if defined(DEV_BRANCH) && defined(USE_I686)
extern CPU cpus_PentiumPro[];
extern CPU cpus_Pentium2[];
extern CPU cpus_Pentium2D[];
#endif
#endif
#define C_FLAG 0x0001
@@ -196,6 +209,9 @@ typedef union {
int16_t sw[4];
uint8_t b[8];
int8_t sb[8];
#ifdef USE_NEW_DYNAREC
float f[2];
#endif
} MMX_REG;
typedef struct {
@@ -259,6 +275,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 +305,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*/
@@ -355,12 +387,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;
@@ -455,8 +491,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 +515,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);
@@ -509,4 +559,3 @@ extern void cpu_ven_reset(void);
#endif /*EMU_CPU_H*/
#endif

View File

@@ -45,9 +45,9 @@
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#include "../86box.h"
#include "86box.h"
#include "cpu.h"
#include "../machine/machine.h"
#include "machine.h"
CPU cpus_8088[] = {
@@ -55,10 +55,10 @@ CPU cpus_8088[] = {
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
};
CPU cpus_pcjr[] = {
@@ -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},
@@ -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

View File

@@ -70,6 +70,9 @@ 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;
#ifdef USE_NEW_DYNAREC
extern const OpFn *x86_dynarec_opcodes_3DNOW;
#endif
extern const OpFn dynarec_ops_286[1024];
extern const OpFn dynarec_ops_286_0f[1024];
@@ -80,13 +83,22 @@ extern const OpFn dynarec_ops_386_0f[1024];
extern const OpFn dynarec_ops_486_0f[1024];
extern const OpFn dynarec_ops_winchip_0f[1024];
#ifdef USE_NEW_DYNAREC
extern const OpFn dynarec_ops_winchip2_0f[1024];
#endif
extern const OpFn dynarec_ops_pentium_0f[1024];
extern const OpFn dynarec_ops_pentiummmx_0f[1024];
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
#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_pentium2d_0f[1024];
@@ -135,6 +147,9 @@ extern const OpFn dynarec_ops_fpu_686_df_a32[256];
extern const OpFn dynarec_ops_REPE[1024];
extern const OpFn dynarec_ops_REPNE[1024];
#ifdef USE_NEW_DYNAREC
extern const OpFn dynarec_ops_3DNOW[256];
#endif
#else
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
#endif
@@ -159,6 +174,9 @@ 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;
#ifdef USE_NEW_DYNAREC
extern const OpFn *x86_opcodes_3DNOW;
#endif
extern const OpFn ops_286[1024];
extern const OpFn ops_286_0f[1024];
@@ -169,14 +187,22 @@ extern const OpFn ops_386_0f[1024];
extern const OpFn ops_486_0f[1024];
extern const OpFn ops_winchip_0f[1024];
#ifdef USE_NEW_DYNAREC
extern const OpFn ops_winchip2_0f[1024];
#endif
extern const OpFn ops_pentium_0f[1024];
extern const OpFn ops_pentiummmx_0f[1024];
#if defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)
#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_pentium2d_0f[1024];
@@ -225,5 +251,13 @@ extern const OpFn ops_fpu_686_df_a32[256];
extern const OpFn ops_REPE[1024];
extern const OpFn ops_REPNE[1024];
#ifdef USE_NEW_DYNAREC
extern const OpFn ops_3DNOW[256];
#endif
#define C0 (1<<8)
#define C1 (1<<9)
#define C2 (1<<10)
#define C3 (1<<14)
#endif /*_X86_OPS_H*/

View File

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

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