mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 10:28:19 -07:00
Merge branch 'master' into global-config-screenshot
This commit is contained in:
53
src/86box.c
53
src/86box.c
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Main emulator module where most things are controlled.
|
||||
* Main emulator module where most things are controlled.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
* Copyright 2021 Laci bá'
|
||||
* Copyright 2021 dob205
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
* Copyright 2021 Laci bá'
|
||||
* Copyright 2021 dob205
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
@@ -205,15 +205,15 @@ char exe_path[2048]; /* path (dir) of executable */
|
||||
char usr_path[1024]; /* path (dir) of user data */
|
||||
char cfg_path[1024]; /* full path of config file */
|
||||
FILE *stdlog = NULL; /* file to log output to */
|
||||
// int scrnsz_x = SCREEN_RES_X; /* current screen size, X */
|
||||
// int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */
|
||||
// int scrnsz_x = SCREEN_RES_X; /* current screen size, X */
|
||||
// int scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */
|
||||
int config_changed; /* config has changed */
|
||||
int title_update;
|
||||
int framecountx = 0;
|
||||
int hard_reset_pending = 0;
|
||||
|
||||
// int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */
|
||||
// int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
|
||||
// int unscaled_size_x = SCREEN_RES_X; /* current unscaled size X */
|
||||
// int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
|
||||
// int efscrnsz_y = SCREEN_RES_Y;
|
||||
|
||||
static wchar_t mouse_msg[3][200];
|
||||
@@ -473,7 +473,7 @@ usage:
|
||||
printf("-D or --debug - force debug output logging\n");
|
||||
#endif
|
||||
#if 0
|
||||
printf("-E or --nographic - forces the old behavior\n");
|
||||
printf("-E or --nographic - forces the old behavior\n");
|
||||
#endif
|
||||
printf("-F or --fullscreen - start in fullscreen mode\n");
|
||||
printf("-G or --lang langid - start with specified language (e.g. en-US, or system)\n");
|
||||
@@ -769,7 +769,7 @@ usage:
|
||||
|
||||
for (i = 0; i < FDD_NUM; i++) {
|
||||
if (fn[i] != NULL) {
|
||||
if (strlen(fn[i]) <= 511)
|
||||
if (strlen(fn[i]) <= 511)
|
||||
strncpy(floppyfns[i], fn[i], 511);
|
||||
free(fn[i]);
|
||||
fn[i] = NULL;
|
||||
@@ -854,7 +854,7 @@ pc_init_modules(void)
|
||||
machine = -1;
|
||||
while (machine_get_internal_name_ex(c) != NULL) {
|
||||
if (machine_available(c)) {
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp);
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
|
||||
machine = c;
|
||||
config_save();
|
||||
break;
|
||||
@@ -877,7 +877,7 @@ pc_init_modules(void)
|
||||
while (video_get_internal_name(c) != NULL) {
|
||||
gfxcard = -1;
|
||||
if (video_card_available(c)) {
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp);
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
|
||||
gfxcard = c;
|
||||
config_save();
|
||||
break;
|
||||
@@ -892,11 +892,10 @@ pc_init_modules(void)
|
||||
}
|
||||
|
||||
if (!video_card_available(gfxcard_2)) {
|
||||
char temp[1024] = { 0 };
|
||||
char tempc[1024] = { 0 };
|
||||
char tempc[512] = { 0 };
|
||||
device_get_name(video_card_getdevice(gfxcard_2), 0, tempc);
|
||||
snprintf(temp, sizeof(temp), "Video card #2 \"%s\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.", tempc);
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2128, temp);
|
||||
swprintf(temp, sizeof(temp), (wchar_t *) "Video card #2 \"%hs\" is not available due to missing ROMs in the roms/video directory. Disabling the second video card.", tempc);
|
||||
ui_msgbox_header(MBX_INFO, (wchar_t *) IDS_2129, temp);
|
||||
gfxcard_2 = 0;
|
||||
}
|
||||
|
||||
@@ -1122,7 +1121,7 @@ pc_reset_hard_init(void)
|
||||
}
|
||||
|
||||
void
|
||||
update_mouse_msg()
|
||||
update_mouse_msg(void)
|
||||
{
|
||||
wchar_t wcpufamily[2048], wcpu[2048], wmachine[2048], *wcp;
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# dob205
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# dob205
|
||||
#
|
||||
# Copyright 2020-2022 David Hrdlička.
|
||||
# Copyright 2021 dob205.
|
||||
# Copyright 2020-2022 David Hrdlička.
|
||||
# Copyright 2021 dob205.
|
||||
#
|
||||
if(APPLE)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
|
||||
@@ -63,7 +63,7 @@ acpi_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
static uint64_t
|
||||
acpi_clock_get()
|
||||
acpi_clock_get(void)
|
||||
{
|
||||
return tsc * cpu_to_acpi;
|
||||
}
|
||||
|
||||
16
src/apm.c
16
src/apm.c
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Advanced Power Management emulation.
|
||||
* Advanced Power Management emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019 Miran Grca.
|
||||
* Copyright 2019 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Configure-time architecture detection for the CMake build.
|
||||
* Configure-time architecture detection for the CMake build.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
* Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
*
|
||||
* Copyright 2020-2021 David Hrdlička.
|
||||
* Copyright 2020-2021 David Hrdlička.
|
||||
*/
|
||||
|
||||
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_mitsumi.c)
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Generic CD-ROM drive core.
|
||||
* Generic CD-ROM drive core.
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2018-2021 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2018-2021 Miran Grca.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* CD-ROM image support.
|
||||
* CD-ROM image support.
|
||||
*
|
||||
* Author: RichardG867,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* bit,
|
||||
*
|
||||
* Copyright 2015-2019 Richardg867.
|
||||
* Copyright 2015-2019 Miran Grca.
|
||||
* Copyright 2017-2019 bit.
|
||||
*
|
||||
* Authors: RichardG867,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* bit,
|
||||
*
|
||||
* Copyright 2015-2019 Richardg867.
|
||||
* Copyright 2015-2019 Miran Grca.
|
||||
* Copyright 2017-2019 bit.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
* CD-ROM image file handling module, translated to C from
|
||||
* cdrom_dosbox.cpp.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* The DOSBox Team, <unknown>
|
||||
@@ -133,7 +135,7 @@ static track_file_t *
|
||||
bin_init(const char *filename, int *error)
|
||||
{
|
||||
track_file_t *tf = (track_file_t *) malloc(sizeof(track_file_t));
|
||||
struct stat stats;
|
||||
struct stat stats;
|
||||
|
||||
if (tf == NULL) {
|
||||
*error = 1;
|
||||
|
||||
@@ -8,13 +8,18 @@
|
||||
*
|
||||
* Virtual ISO CD-ROM image back-end.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: RichardG <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2022 RichardG.
|
||||
*/
|
||||
// clang-format off
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _LARGEFILE64_SOURCE
|
||||
#ifndef _LARGEFILE_SOURCE
|
||||
# define _LARGEFILE_SOURCE
|
||||
#endif
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
# define _LARGEFILE64_SOURCE
|
||||
#endif
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <ctype.h>
|
||||
#include <inttypes.h>
|
||||
@@ -36,7 +41,6 @@
|
||||
#include <86box/version.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
// clang-format on
|
||||
|
||||
#ifndef S_ISDIR
|
||||
# define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR)
|
||||
@@ -85,9 +89,9 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
VISO_FORMAT_HSF = 0, /* High Sierra */
|
||||
VISO_FORMAT_ISO, /* ISO 9660 */
|
||||
VISO_FORMAT_ISO_LFN /* ISO 9660 with Joliet and Rock Ridge */
|
||||
VISO_FORMAT_ISO = 1, /* ISO 9660 (High Sierra if not set) */
|
||||
VISO_FORMAT_JOLIET = 2, /* Joliet extensions (Microsoft) */
|
||||
VISO_FORMAT_RR = 4 /* Rock Ridge extensions (*nix) */
|
||||
};
|
||||
|
||||
typedef struct _viso_entry_ {
|
||||
@@ -111,7 +115,7 @@ typedef struct _viso_entry_ {
|
||||
|
||||
typedef struct {
|
||||
uint64_t vol_size_offsets[2], pt_meta_offsets[2];
|
||||
int format;
|
||||
int format, use_version_suffix : 1;
|
||||
size_t metadata_sectors, all_sectors, entry_map_size, sector_size, file_fifo_pos;
|
||||
uint8_t *metadata;
|
||||
|
||||
@@ -296,7 +300,7 @@ static int
|
||||
viso_fill_fn_short(char *data, const viso_entry_t *entry, viso_entry_t **entries)
|
||||
{
|
||||
/* Get name and extension length. */
|
||||
const char *ext_pos = S_ISDIR(entry->stats.st_mode) ? NULL : strrchr(entry->basename, '.');
|
||||
const char *ext_pos = strrchr(entry->basename, '.');
|
||||
int name_len, ext_len;
|
||||
if (ext_pos) {
|
||||
name_len = ext_pos - entry->basename;
|
||||
@@ -440,7 +444,7 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
|
||||
time_s->tm_mday = 1;
|
||||
} else if (time_s->tm_year > (longform ? 8099 : 255)) {
|
||||
time_s->tm_year = longform ? 8099 : 255;
|
||||
time_s->tm_mon = 12;
|
||||
time_s->tm_mon = 11;
|
||||
time_s->tm_mday = 31;
|
||||
time_s->tm_hour = 23;
|
||||
time_s->tm_min = time_s->tm_sec = 59;
|
||||
@@ -459,14 +463,14 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
|
||||
*p++ = time_s->tm_min; /* minute */
|
||||
*p++ = time_s->tm_sec; /* second */
|
||||
}
|
||||
if (format >= VISO_FORMAT_ISO)
|
||||
if (format & VISO_FORMAT_ISO)
|
||||
*p++ = tz_offset; /* timezone (ISO only) */
|
||||
|
||||
return p - data;
|
||||
}
|
||||
|
||||
static int
|
||||
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
|
||||
{
|
||||
uint8_t *p = data, *q, *r;
|
||||
|
||||
@@ -478,11 +482,11 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
if (entry->stats.st_mtime < 0)
|
||||
pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path);
|
||||
#endif
|
||||
p += viso_fill_time(p, entry->stats.st_mtime, format, 0); /* time */
|
||||
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
|
||||
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */
|
||||
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
|
||||
|
||||
VISO_SKIP(p, 2 + (format <= VISO_FORMAT_HSF)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */
|
||||
VISO_LBE_16(p, 1); /* volume sequence number */
|
||||
VISO_SKIP(p, 2 + !(viso->format & VISO_FORMAT_ISO)); /* file unit size (reserved on HSF), interleave gap size (HSF/ISO) and skip factor (HSF only) */
|
||||
VISO_LBE_16(p, 1); /* volume sequence number */
|
||||
|
||||
switch (type) {
|
||||
case VISO_DIR_CURRENT:
|
||||
@@ -492,7 +496,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
*p++ = (type == VISO_DIR_PARENT) ? 1 : 0; /* magic value corresponding to . or .. */
|
||||
|
||||
/* Fill Rock Ridge Extension Record for the root directory's . entry. */
|
||||
if ((type == VISO_DIR_CURRENT_ROOT) && (format >= VISO_FORMAT_ISO_LFN)) {
|
||||
if ((type == VISO_DIR_CURRENT_ROOT) && (viso->format & VISO_FORMAT_RR)) {
|
||||
*p++ = 'E';
|
||||
*p++ = 'R';
|
||||
*p++ = 8 + (sizeof(rr_eid) - 1) + (sizeof(rr_edesc) - 1); /* length */
|
||||
@@ -518,8 +522,8 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
*q = strlen(entry->name_short);
|
||||
memcpy(p, entry->name_short, *q); /* file ID */
|
||||
p += *q;
|
||||
if ((format >= VISO_FORMAT_ISO) && !S_ISDIR(entry->stats.st_mode)) {
|
||||
*p++ = ';'; /* version suffix for files (ISO only?) */
|
||||
if (viso->use_version_suffix && !S_ISDIR(entry->stats.st_mode)) {
|
||||
*p++ = ';'; /* version suffix for files (ISO only, except for Windows NT SETUPLDR.BIN El Torito hack) */
|
||||
*p++ = '1';
|
||||
*q += 2;
|
||||
}
|
||||
@@ -528,7 +532,7 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
*p++ = 0;
|
||||
|
||||
/* Fill Rock Ridge data. */
|
||||
if (format >= VISO_FORMAT_ISO_LFN) {
|
||||
if (viso->format & VISO_FORMAT_RR) {
|
||||
*p++ = 'R'; /* RR = present Rock Ridge entries (only documented by RRIP revision 1.09!) */
|
||||
*p++ = 'R';
|
||||
*p++ = 5; /* length */
|
||||
@@ -584,14 +588,14 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, int format, int type)
|
||||
*p++ = times; /* flags */
|
||||
#ifdef st_birthtime
|
||||
if (times & (1 << 0))
|
||||
p += viso_fill_time(p, entry->stats.st_birthtime, format, 0); /* creation */
|
||||
p += viso_fill_time(p, entry->stats.st_birthtime, viso->format, 0); /* creation */
|
||||
#endif
|
||||
if (times & (1 << 1))
|
||||
p += viso_fill_time(p, entry->stats.st_mtime, format, 0); /* modify */
|
||||
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* modify */
|
||||
if (times & (1 << 2))
|
||||
p += viso_fill_time(p, entry->stats.st_atime, format, 0); /* access */
|
||||
p += viso_fill_time(p, entry->stats.st_atime, viso->format, 0); /* access */
|
||||
if (times & (1 << 3))
|
||||
p += viso_fill_time(p, entry->stats.st_ctime, format, 0); /* attributes */
|
||||
p += viso_fill_time(p, entry->stats.st_ctime, viso->format, 0); /* attributes */
|
||||
|
||||
*r += p - r; /* add to length */
|
||||
}
|
||||
@@ -760,8 +764,9 @@ viso_init(const char *dirname, int *error)
|
||||
*error = 1;
|
||||
if (viso == NULL)
|
||||
goto end;
|
||||
viso->sector_size = VISO_SECTOR_SIZE;
|
||||
viso->format = VISO_FORMAT_ISO_LFN;
|
||||
viso->sector_size = VISO_SECTOR_SIZE;
|
||||
viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR;
|
||||
viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */
|
||||
|
||||
/* Prepare temporary data buffers. */
|
||||
data = calloc(2, viso->sector_size);
|
||||
@@ -793,7 +798,6 @@ viso_init(const char *dirname, int *error)
|
||||
if (!dir)
|
||||
goto end;
|
||||
strcpy(dir->path, dirname);
|
||||
strcpy(dir->name_short, "[root]");
|
||||
if (stat(dirname, &dir->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&dir->stats, 0x00, sizeof(struct stat));
|
||||
@@ -801,7 +805,7 @@ viso_init(const char *dirname, int *error)
|
||||
if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */
|
||||
goto end;
|
||||
dir->parent = dir; /* for the root's path table and .. entries */
|
||||
cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, dir->name_short);
|
||||
cdrom_image_viso_log("[%08X] %s => [root]\n", dir, dir->path);
|
||||
|
||||
/* Traverse directories, starting with the root. */
|
||||
viso_entry_t **dir_entries = NULL;
|
||||
@@ -809,16 +813,16 @@ viso_init(const char *dirname, int *error)
|
||||
while (dir) {
|
||||
/* Open directory for listing. */
|
||||
DIR *dirp = opendir(dir->path);
|
||||
if (!dirp)
|
||||
goto next_dir;
|
||||
|
||||
/* Iterate through this directory's children to determine the entry array size. */
|
||||
size_t children_count = 3; /* include terminator, . and .. */
|
||||
while ((readdir_entry = readdir(dirp))) {
|
||||
/* Ignore . and .. pseudo-directories. */
|
||||
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || ((readdir_entry->d_name[1] == '.') && (readdir_entry->d_name[2] == '\0'))))
|
||||
continue;
|
||||
children_count++;
|
||||
if (dirp) { /* create empty directory if opendir failed */
|
||||
while ((readdir_entry = readdir(dirp))) {
|
||||
/* Ignore . and .. pseudo-directories. */
|
||||
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
|
||||
continue;
|
||||
children_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grow array if needed. */
|
||||
@@ -855,77 +859,89 @@ viso_init(const char *dirname, int *error)
|
||||
}
|
||||
|
||||
/* Iterate through this directory's children again, making the entries. */
|
||||
rewinddir(dirp);
|
||||
while ((readdir_entry = readdir(dirp))) {
|
||||
/* Ignore . and .. pseudo-directories. */
|
||||
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || ((readdir_entry->d_name[1] == '.') && (readdir_entry->d_name[2] == '\0'))))
|
||||
continue;
|
||||
if (dirp) {
|
||||
rewinddir(dirp);
|
||||
while ((readdir_entry = readdir(dirp))) {
|
||||
/* Ignore . and .. pseudo-directories. */
|
||||
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
|
||||
continue;
|
||||
|
||||
/* Add and fill entry. */
|
||||
entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2);
|
||||
if (!entry)
|
||||
break;
|
||||
entry->parent = dir;
|
||||
strcpy(entry->path, dir->path);
|
||||
path_slash(&entry->path[dir_path_len]);
|
||||
entry->basename = &entry->path[dir_path_len + 1];
|
||||
strcpy(entry->basename, readdir_entry->d_name);
|
||||
/* Add and fill entry. */
|
||||
entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2);
|
||||
if (!entry)
|
||||
break;
|
||||
entry->parent = dir;
|
||||
strcpy(entry->path, dir->path);
|
||||
path_slash(&entry->path[dir_path_len]);
|
||||
entry->basename = &entry->path[dir_path_len + 1];
|
||||
strcpy(entry->basename, readdir_entry->d_name);
|
||||
|
||||
/* Stat this child. */
|
||||
if (stat(entry->path, &entry->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&entry->stats, 0x00, sizeof(struct stat));
|
||||
}
|
||||
|
||||
/* Handle file size and El Torito boot code. */
|
||||
if (!S_ISDIR(entry->stats.st_mode)) {
|
||||
/* Clamp to 4 GB - 1 byte. */
|
||||
if (entry->stats.st_size > ((uint32_t) -1))
|
||||
entry->stats.st_size = (uint32_t) -1;
|
||||
|
||||
/* Increase entry map size. */
|
||||
viso->entry_map_size += entry->stats.st_size / viso->sector_size;
|
||||
if (entry->stats.st_size % viso->sector_size)
|
||||
viso->entry_map_size++; /* round up to the next sector */
|
||||
|
||||
/* Detect El Torito boot code file and set it accordingly. */
|
||||
if (dir == eltorito_dir) {
|
||||
if (!stricmp(readdir_entry->d_name, "Boot-NoEmul.img")) {
|
||||
eltorito_type = 0x00;
|
||||
have_eltorito_entry:
|
||||
if (eltorito_entry)
|
||||
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||
eltorito_entry = entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-1.2M.img")) {
|
||||
eltorito_type = 0x01;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-1.44M.img")) {
|
||||
eltorito_type = 0x02;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-2.88M.img")) {
|
||||
eltorito_type = 0x03;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-HardDisk.img")) {
|
||||
eltorito_type = 0x04;
|
||||
goto have_eltorito_entry;
|
||||
} else {
|
||||
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||
}
|
||||
/* Stat this child. */
|
||||
if (stat(entry->path, &entry->stats) != 0) {
|
||||
/* Use a blank structure if stat failed. */
|
||||
memset(&entry->stats, 0x00, sizeof(struct stat));
|
||||
}
|
||||
} else if ((dir == viso->root_dir) && !stricmp(readdir_entry->d_name, "[BOOT]")) {
|
||||
/* Set this as the directory containing El Torito boot code. */
|
||||
eltorito_dir = entry;
|
||||
eltorito_others_present = 0;
|
||||
}
|
||||
|
||||
/* Set short filename. */
|
||||
if (viso_fill_fn_short(entry->name_short, entry, dir_entries)) {
|
||||
free(entry);
|
||||
children_count--;
|
||||
continue;
|
||||
}
|
||||
/* Handle file size and El Torito boot code. */
|
||||
if (!S_ISDIR(entry->stats.st_mode)) {
|
||||
/* Clamp file size to 4 GB - 1 byte. */
|
||||
if (entry->stats.st_size > ((uint32_t) -1))
|
||||
entry->stats.st_size = (uint32_t) -1;
|
||||
|
||||
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename);
|
||||
/* Increase entry map size. */
|
||||
viso->entry_map_size += entry->stats.st_size / viso->sector_size;
|
||||
if (entry->stats.st_size % viso->sector_size)
|
||||
viso->entry_map_size++; /* round up to the next sector */
|
||||
|
||||
/* Detect El Torito boot code file and set it accordingly. */
|
||||
if (dir == eltorito_dir) {
|
||||
if (!stricmp(readdir_entry->d_name, "Boot-NoEmul.img")) {
|
||||
eltorito_type = 0x00;
|
||||
have_eltorito_entry:
|
||||
if (eltorito_entry)
|
||||
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||
eltorito_entry = entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-1.2M.img")) {
|
||||
eltorito_type = 0x01;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-1.44M.img")) {
|
||||
eltorito_type = 0x02;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-2.88M.img")) {
|
||||
eltorito_type = 0x03;
|
||||
goto have_eltorito_entry;
|
||||
} else if (!stricmp(readdir_entry->d_name, "Boot-HardDisk.img")) {
|
||||
eltorito_type = 0x04;
|
||||
goto have_eltorito_entry;
|
||||
} else {
|
||||
eltorito_others_present = 1; /* flag that the boot code directory contains other files */
|
||||
}
|
||||
} else {
|
||||
/* Disable version suffixes if this structure appears to contain the Windows NT
|
||||
El Torito boot code, which is known not to tolerate suffixed file names. */
|
||||
if (eltorito_dir && /* El Torito directory present? */
|
||||
(eltorito_type == 0x00) && /* El Torito directory not checked yet, or confirmed to contain non-emulation boot code? */
|
||||
(dir->parent == viso->root_dir) && /* one subdirectory deep? (I386 for instance) */
|
||||
!stricmp(readdir_entry->d_name, "SETUPLDR.BIN")) /* SETUPLDR.BIN present? */
|
||||
viso->use_version_suffix = 0;
|
||||
}
|
||||
} else if ((dir == viso->root_dir) && !stricmp(readdir_entry->d_name, "[BOOT]")) {
|
||||
/* Set this as the directory containing El Torito boot code. */
|
||||
eltorito_dir = entry;
|
||||
eltorito_others_present = 0;
|
||||
}
|
||||
|
||||
/* Set short filename. */
|
||||
if (viso_fill_fn_short(entry->name_short, entry, dir_entries)) {
|
||||
free(entry);
|
||||
children_count--;
|
||||
continue;
|
||||
}
|
||||
|
||||
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename);
|
||||
}
|
||||
} else {
|
||||
cdrom_image_viso_log("VISO: Failed to enumerate [%s], will be empty\n", dir->path);
|
||||
}
|
||||
|
||||
/* Add terminator. */
|
||||
@@ -947,6 +963,8 @@ have_eltorito_entry:
|
||||
|
||||
next_dir:
|
||||
/* Move on to the next directory. */
|
||||
if (dirp)
|
||||
closedir(dirp);
|
||||
dir = dir->next_dir;
|
||||
}
|
||||
if (dir_entries)
|
||||
@@ -960,21 +978,26 @@ next_dir:
|
||||
the timezone offset for descriptors and file times to use. */
|
||||
tzset();
|
||||
time_t now = time(NULL);
|
||||
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
|
||||
if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */
|
||||
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
|
||||
|
||||
/* Get root directory basename for the volume ID. */
|
||||
char *basename = path_get_filename(viso->root_dir->path);
|
||||
if (!basename || (basename[0] == '\0'))
|
||||
basename = EMU_NAME;
|
||||
|
||||
/* Determine whether or not we're working with 2 volume descriptors
|
||||
(as well as 2 directory trees and 4 path tables) for Joliet. */
|
||||
int max_vd = (viso->format & VISO_FORMAT_JOLIET) ? 1 : 0;
|
||||
|
||||
/* Write volume descriptors. */
|
||||
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) {
|
||||
for (int i = 0; i <= max_vd; i++) {
|
||||
/* Fill volume descriptor. */
|
||||
p = data;
|
||||
if (viso->format <= VISO_FORMAT_HSF)
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 1 + i; /* type */
|
||||
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */
|
||||
if (!(viso->format & VISO_FORMAT_ISO))
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 1 + i; /* type */
|
||||
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
|
||||
p += 5;
|
||||
*p++ = 1; /* version */
|
||||
*p++ = 0; /* unused */
|
||||
@@ -1013,11 +1036,12 @@ next_dir:
|
||||
|
||||
/* Path table metadata is filled in later. */
|
||||
viso->pt_meta_offsets[i] = ftello64(viso->tf.file) + (p - data);
|
||||
VISO_SKIP(p, 24 + (16 * (viso->format <= VISO_FORMAT_HSF))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */
|
||||
VISO_SKIP(p, 24 + (16 * !(viso->format & VISO_FORMAT_ISO))); /* PT size, LE PT offset, optional LE PT offset (three on HSF), BE PT offset, optional BE PT offset (three on HSF) */
|
||||
|
||||
viso->root_dir->dr_offsets[i] = ftello64(viso->tf.file) + (p - data);
|
||||
p += viso_fill_dir_record(p, viso->root_dir, viso->format, VISO_DIR_CURRENT); /* root directory */
|
||||
p += viso_fill_dir_record(p, viso->root_dir, viso, VISO_DIR_CURRENT); /* root directory */
|
||||
|
||||
int copyright_abstract_len = (viso->format & VISO_FORMAT_ISO) ? 37 : 32;
|
||||
if (i) {
|
||||
viso_write_wstring((uint16_t *) p, L"", 64, VISO_CHARSET_D); /* volume set ID */
|
||||
p += 128;
|
||||
@@ -1027,11 +1051,11 @@ next_dir:
|
||||
p += 128;
|
||||
viso_write_wstring((uint16_t *) p, EMU_NAME_W L" " EMU_VERSION_W L" VIRTUAL ISO", 64, VISO_CHARSET_A); /* application ID */
|
||||
p += 128;
|
||||
viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* copyright file ID */
|
||||
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37;
|
||||
viso_write_wstring((uint16_t *) p, L"", (viso->format <= VISO_FORMAT_HSF) ? 16 : 18, VISO_CHARSET_D); /* abstract file ID */
|
||||
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37;
|
||||
if (viso->format >= VISO_FORMAT_ISO) {
|
||||
viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* copyright file ID */
|
||||
p += copyright_abstract_len;
|
||||
viso_write_wstring((uint16_t *) p, L"", copyright_abstract_len >> 1, VISO_CHARSET_D); /* abstract file ID */
|
||||
p += copyright_abstract_len;
|
||||
if (viso->format & VISO_FORMAT_ISO) {
|
||||
viso_write_wstring((uint16_t *) p, L"", 18, VISO_CHARSET_D); /* bibliography file ID (ISO only) */
|
||||
p += 37;
|
||||
}
|
||||
@@ -1044,11 +1068,11 @@ next_dir:
|
||||
p += 128;
|
||||
viso_write_string(p, EMU_NAME " " EMU_VERSION " VIRTUAL ISO", 128, VISO_CHARSET_A); /* application ID */
|
||||
p += 128;
|
||||
viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* copyright file ID */
|
||||
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37;
|
||||
viso_write_string(p, "", (viso->format <= VISO_FORMAT_HSF) ? 32 : 37, VISO_CHARSET_D); /* abstract file ID */
|
||||
p += (viso->format <= VISO_FORMAT_HSF) ? 32 : 37;
|
||||
if (viso->format >= VISO_FORMAT_ISO) {
|
||||
viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* copyright file ID */
|
||||
p += copyright_abstract_len;
|
||||
viso_write_string(p, "", copyright_abstract_len, VISO_CHARSET_D); /* abstract file ID */
|
||||
p += copyright_abstract_len;
|
||||
if (viso->format & VISO_FORMAT_ISO) {
|
||||
viso_write_string(p, "", 37, VISO_CHARSET_D); /* bibliography file ID (ISO only) */
|
||||
p += 37;
|
||||
}
|
||||
@@ -1074,10 +1098,10 @@ next_dir:
|
||||
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry);
|
||||
|
||||
p = data;
|
||||
if (viso->format <= VISO_FORMAT_HSF)
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 0; /* type */
|
||||
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */
|
||||
if (!(viso->format & VISO_FORMAT_ISO))
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 0; /* type */
|
||||
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
|
||||
p += 5;
|
||||
*p++ = 1; /* version */
|
||||
|
||||
@@ -1098,10 +1122,10 @@ next_dir:
|
||||
|
||||
/* Fill terminator. */
|
||||
p = data;
|
||||
if (viso->format <= VISO_FORMAT_HSF)
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 0xff; /* type */
|
||||
memcpy(p, (viso->format <= VISO_FORMAT_HSF) ? "CDROM" : "CD001", 5); /* standard ID */
|
||||
if (!(viso->format & VISO_FORMAT_ISO))
|
||||
VISO_LBE_32(p, ftello64(viso->tf.file) / viso->sector_size); /* sector offset (HSF only) */
|
||||
*p++ = 0xff; /* type */
|
||||
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
|
||||
p += 5;
|
||||
*p++ = 1; /* version */
|
||||
|
||||
@@ -1177,7 +1201,7 @@ next_dir:
|
||||
}
|
||||
|
||||
/* Write each path table. */
|
||||
for (int i = 0; i <= ((viso->format >= VISO_FORMAT_ISO_LFN) ? 3 : 1); i++) {
|
||||
for (int i = 0; i <= ((max_vd << 1) | 1); i++) {
|
||||
cdrom_image_viso_log("VISO: Generating path table #%d:\n", i);
|
||||
|
||||
/* Save this path table's start offset. */
|
||||
@@ -1207,7 +1231,7 @@ next_dir:
|
||||
|
||||
/* Fill path table entry. */
|
||||
p = data;
|
||||
if (viso->format <= VISO_FORMAT_HSF) {
|
||||
if (!(viso->format & VISO_FORMAT_ISO)) {
|
||||
*((uint32_t *) p) = 0; /* extent location (filled in later) */
|
||||
p += 4;
|
||||
*p++ = 0; /* extended attribute length */
|
||||
@@ -1223,16 +1247,17 @@ next_dir:
|
||||
*((uint16_t *) p) = (i & 1) ? cpu_to_be16(dir->parent->pt_idx) : cpu_to_le16(dir->parent->pt_idx); /* parent directory number */
|
||||
p += 2;
|
||||
|
||||
if (dir == viso->root_dir) { /* directory ID and length */
|
||||
data[5 * (viso->format <= VISO_FORMAT_HSF)] = 1;
|
||||
*p = 0x00;
|
||||
} else if (i & 2) {
|
||||
data[5 * (viso->format <= VISO_FORMAT_HSF)] = viso_fill_fn_joliet(p, dir, 255);
|
||||
} else {
|
||||
data[5 * (viso->format <= VISO_FORMAT_HSF)] = strlen(dir->name_short);
|
||||
memcpy(p, dir->name_short, data[5 * (viso->format <= VISO_FORMAT_HSF)]);
|
||||
pt_temp = 5 * !(viso->format & VISO_FORMAT_ISO); /* directory ID length at offset 0 for ISO, 5 for HSF */
|
||||
if (dir == viso->root_dir) { /* directory ID length then ID for root... */
|
||||
data[pt_temp] = 1;
|
||||
*p = 0x00;
|
||||
} else if (i & 2) { /* ...or Joliet... */
|
||||
data[pt_temp] = viso_fill_fn_joliet(p, dir, 255);
|
||||
} else { /* ...or short name */
|
||||
data[pt_temp] = strlen(dir->name_short);
|
||||
memcpy(p, dir->name_short, data[pt_temp]);
|
||||
}
|
||||
p += data[5 * (viso->format <= VISO_FORMAT_HSF)];
|
||||
p += data[pt_temp];
|
||||
|
||||
if ((p - data) & 1) /* padding for odd directory ID lengths */
|
||||
*p++ = 0x00;
|
||||
@@ -1265,7 +1290,7 @@ next_dir:
|
||||
|
||||
/* Write directory records for each type. */
|
||||
int dir_type = VISO_DIR_CURRENT_ROOT;
|
||||
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++) {
|
||||
for (int i = 0; i <= max_vd; i++) {
|
||||
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
|
||||
|
||||
/* Go through directories. */
|
||||
@@ -1298,7 +1323,7 @@ next_dir:
|
||||
viso_pwrite(data, dir->pt_offsets[i << 1], 4, 1, viso->tf.file); /* little endian */
|
||||
viso_pwrite(data + 4, dir->pt_offsets[(i << 1) | 1], 4, 1, viso->tf.file); /* big endian */
|
||||
|
||||
if (i == (viso->format >= VISO_FORMAT_ISO_LFN)) /* overwrite pt_offsets in the union if we no longer need them */
|
||||
if (i == max_vd) /* overwrite pt_offsets in the union if we no longer need them */
|
||||
dir->file = NULL;
|
||||
|
||||
/* Go through entries in this directory. */
|
||||
@@ -1313,7 +1338,7 @@ next_dir:
|
||||
((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short))));
|
||||
|
||||
/* Fill directory record. */
|
||||
viso_fill_dir_record(data, entry, viso->format, dir_type);
|
||||
viso_fill_dir_record(data, entry, viso, dir_type);
|
||||
|
||||
/* Entries cannot cross sector boundaries, so pad to the next sector if needed. */
|
||||
write = viso->sector_size - (ftello64(viso->tf.file) % viso->sector_size);
|
||||
@@ -1452,7 +1477,7 @@ next_entry:
|
||||
} else {
|
||||
p = data;
|
||||
VISO_LBE_32(p, viso->all_sectors * base_factor);
|
||||
for (int i = 0; i <= (viso->format >= VISO_FORMAT_ISO_LFN); i++)
|
||||
for (int i = 0; i <= max_vd; i++)
|
||||
viso_pwrite(data, entry->dr_offsets[i] + 2, 8, 1, viso->tf.file);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Mitsumi CD-ROM emulation for the ISA bus.
|
||||
* Mitsumi CD-ROM emulation for the ISA bus.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2022 Miran Grca.
|
||||
* Copyright 2022 Miran Grca.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
@@ -183,7 +183,7 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first)
|
||||
return 0;
|
||||
}
|
||||
cdrom_stop(cdrom);
|
||||
ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, &dev->readcount);
|
||||
ret = cdrom_readsector_raw(cdrom, dev->buf, cdrom->seek_pos, 0, 2, 0x10, (int *) &dev->readcount);
|
||||
if (!ret)
|
||||
return 0;
|
||||
if (dev->mode & 0x40) {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Chips&Technology's 82C100 chipset.
|
||||
* Implementation of Chips&Technology's 82C100 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ACC 2046/2168 chipset
|
||||
* Implementation of the ACC 2046/2168 chipset
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Tiseno100
|
||||
*
|
||||
* Copyright 2019 Sarah Walker.
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2019 Sarah Walker.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1429 chipset.
|
||||
* Implementation of the ALi M1429 chipset.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2021,2021 Miran Grca.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2021,2021 Miran Grca.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -72,7 +74,6 @@
|
||||
1 1 0: CLK2IN/12
|
||||
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -323,8 +324,8 @@ ali1429_init(const device_t *info)
|
||||
GREEN = info->local;
|
||||
|
||||
/* M1429 Ports:
|
||||
22h Index Port
|
||||
23h Data Port
|
||||
22h Index Port
|
||||
23h Data Port
|
||||
*/
|
||||
io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev);
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1489 chipset.
|
||||
* Implementation of the ALi M1489 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2020,2021 Miran Grca.
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2020,2021 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1531B CPU-to-PCI Bridge.
|
||||
* Implementation of the ALi M1531B CPU-to-PCI Bridge.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1541/2 CPU-to-PCI Bridge.
|
||||
* Implementation of the ALi M1541/2 CPU-to-PCI Bridge.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1543 Desktop South Bridge.
|
||||
* Implementation of the ALi M1543 Desktop South Bridge.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M1621/2 CPU-to-PCI Bridge.
|
||||
* Implementation of the ALi M1621/2 CPU-to-PCI Bridge.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -57,28 +59,28 @@ ali1621_log(const char *fmt, ...)
|
||||
|
||||
/* Table translated to a more sensible format:
|
||||
Read cycles:
|
||||
SMREN SMM Mode Code Data
|
||||
0 X X PCI PCI
|
||||
1 0 Close PCI PCI
|
||||
1 0 Lock PCI PCI
|
||||
1 0 Protect PCI PCI
|
||||
1 0 Open DRAM DRAM
|
||||
1 1 Open DRAM DRAM
|
||||
1 1 Protect DRAM DRAM
|
||||
1 1 Close DRAM PCI
|
||||
1 1 Lock DRAM PCI
|
||||
SMREN SMM Mode Code Data
|
||||
0 X X PCI PCI
|
||||
1 0 Close PCI PCI
|
||||
1 0 Lock PCI PCI
|
||||
1 0 Protect PCI PCI
|
||||
1 0 Open DRAM DRAM
|
||||
1 1 Open DRAM DRAM
|
||||
1 1 Protect DRAM DRAM
|
||||
1 1 Close DRAM PCI
|
||||
1 1 Lock DRAM PCI
|
||||
|
||||
Write cycles:
|
||||
SMWEN SMM Mode Data
|
||||
0 X X PCI
|
||||
1 0 Close PCI
|
||||
1 0 Lock PCI
|
||||
1 0 Protect PCI
|
||||
1 0 Open DRAM
|
||||
1 1 Open DRAM
|
||||
1 1 Protect DRAM
|
||||
1 1 Close PCI
|
||||
1 1 Lock PCI
|
||||
SMWEN SMM Mode Data
|
||||
0 X X PCI
|
||||
1 0 Close PCI
|
||||
1 0 Lock PCI
|
||||
1 0 Protect PCI
|
||||
1 0 Open DRAM
|
||||
1 1 Open DRAM
|
||||
1 1 Protect DRAM
|
||||
1 1 Close PCI
|
||||
1 1 Lock PCI
|
||||
|
||||
Explanation of the modes based above:
|
||||
If SM*EN = 0, SMRAM is entirely disabled, otherwise:
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ALi M6117 SoC.
|
||||
* Implementation of the ALi M6117 SoC.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2020 RichardG.
|
||||
* Copyright 2020 RichardG.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
|
||||
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Chips & Technologies CS4031 chipset.
|
||||
* Implementation of the Chips & Technologies CS4031 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of C&T CS8230 ("386/AT") chipset.
|
||||
* Emulation of C&T CS8230 ("386/AT") chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
*
|
||||
* Copyright 2020 Sarah Walker.
|
||||
* Copyright 2020 Sarah Walker.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the ETEQ Cheetah ET6000 chipset.
|
||||
* Implementation of the ETEQ Cheetah ET6000 chipset.
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the G2 GC100/GC100A chipset.
|
||||
* NOTE: As documentation is currently available only for the
|
||||
* CG100 chipset, the GC100A chipset has been reverese-engineered.
|
||||
* Thus, its behavior may not be fully accurate.
|
||||
* Implementation of the G2 GC100/GC100A chipset.
|
||||
*
|
||||
* Authors: EngiNerd, <webmaster.crrc@yahoo.it>
|
||||
* NOTE: As documentation is currently available only for the
|
||||
* GC100 chipset, the GC100A chipset has been reverese-engineered.
|
||||
* Thus, its behavior may not be fully accurate.
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd.
|
||||
*
|
||||
*
|
||||
* Authors: EngiNerd, <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the HEADLAND AT286 chipset.
|
||||
* Implementation of the HEADLAND AT286 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Original by GreatPsycho for PCem.
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Original by GreatPsycho for PCem.
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2010-2019 Sarah Walker.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Miran Grca.
|
||||
* Copyright 2017-2019 GreatPsycho.
|
||||
* Copyright 2010-2019 Sarah Walker.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 Miran Grca.
|
||||
* Copyright 2017-2019 GreatPsycho.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -255,7 +255,7 @@ memmap_state_update(headland_t *dev)
|
||||
mem_mapping_set_exec(&dev->high_mapping, ram + 0x100000);
|
||||
}
|
||||
} else {
|
||||
/* 1 MB - 1 MB + 384k: RAM pointing to A0000-FFFFF
|
||||
/* 1 MB - 1 MB + 384k: RAM pointing to A0000-FFFFF
|
||||
1 MB + 384k: Any ram pointing 1 MB onwards. */
|
||||
/* First, do the addresses above 1 MB. */
|
||||
mem_mapping_set_addr(&dev->mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10);
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the IMS 8848/8849 chipset.
|
||||
* Implementation of the IMS 8848/8849 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100,
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of Intel 82420EX chipset that acts as both the
|
||||
* northbridge and the southbridge.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of Intel 82420EX chipset that acts as both the
|
||||
* northbridge and the southbridge.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel PCISet chips from 420TX to 440GX.
|
||||
* Implementation of the Intel PCISet chips from 420TX to 440GX.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019,2020 Miran Grca.
|
||||
* Copyright 2019-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel 82335(KU82335) chipset.
|
||||
* Implementation of the Intel 82335(KU82335) chipset.
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel 450KX Mars Chipset.
|
||||
* Implementation of the Intel 450KX Mars Chipset.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -19,7 +21,6 @@ Due to 86Box limitations we can't manage them seperately thus it is dev branch t
|
||||
|
||||
i450GX is way more popular of an option but needs more stuff.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC
|
||||
* SLC90E66 (Victory66) Xcelerators.
|
||||
* Emulation of the Intel PIIX, PIIX3, PIIX4, PIIX4E, and SMSC
|
||||
* SLC90E66 (Victory66) Xcelerators.
|
||||
*
|
||||
* PRD format :
|
||||
* word 0 - base address
|
||||
* word 1 - bits 1-15 = byte count, bit 31 = end of transfer
|
||||
* PRD format :
|
||||
* word 0 - base address
|
||||
* word 1 - bits 1-15 = byte count, bit 31 = end of transfer
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -1023,9 +1023,9 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
fregs[0x07] &= 0xf7;
|
||||
break;
|
||||
#if 0
|
||||
case 0x3c:
|
||||
fregs[0x3c] = val;
|
||||
break;
|
||||
case 0x3c:
|
||||
fregs[0x3c] = val;
|
||||
break;
|
||||
#endif
|
||||
case 0x40:
|
||||
fregs[0x40] = (val & 0xc0) | 1;
|
||||
@@ -1657,9 +1657,9 @@ static void
|
||||
/* Bit 5: 0 = CMOS Setup disabled, 1 = CMOS Setup enabled. */
|
||||
/* Bit 4: External CPU clock (Switch 8). */
|
||||
/* Bit 3: External CPU clock (Switch 7). */
|
||||
/* 50 MHz: Switch 7 = Off, Switch 8 = Off. */
|
||||
/* 60 MHz: Switch 7 = On, Switch 8 = Off. */
|
||||
/* 66 MHz: Switch 7 = Off, Switch 8 = On. */
|
||||
/* 50 MHz: Switch 7 = Off, Switch 8 = Off. */
|
||||
/* 60 MHz: Switch 7 = On, Switch 8 = Off. */
|
||||
/* 66 MHz: Switch 7 = Off, Switch 8 = On. */
|
||||
/* Bit 2: 0 = On-board audio absent, 1 = On-board audio present. */
|
||||
/* Bit 1: 0 = Soft-off capable power supply present, 1 = Soft-off capable power supply absent. */
|
||||
/* Bit 0: 0 = 1.5x multiplier, 1 = 2x multiplier (Switch 6). */
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of Intel System I/O PCI chip.
|
||||
* Emulation of Intel System I/O PCI chip.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset.
|
||||
* Emulation of C&T CS8121 ("NEAT") 82C206/211/212/215 chipset.
|
||||
*
|
||||
* Note: The datasheet mentions that the chipset supports up to 8MB
|
||||
* of DRAM. This is intepreted as 'being able to refresh up to
|
||||
* 8MB of DRAM chips', because it works fine with bus-based
|
||||
* memory expansion.
|
||||
* Note: The datasheet mentions that the chipset supports up to 8MB
|
||||
* of DRAM. This is intepreted as 'being able to refresh up to
|
||||
* 8MB of DRAM chips', because it works fine with bus-based
|
||||
* memory expansion.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2018 Fred N. van Kempen.
|
||||
* Copyright 2018 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Olivetti EVA (98/86) Gate Array.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Implementation of the Olivetti EVA (98/86) Gate Array.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2021 EngiNerd
|
||||
* Copyright 2020-2021 EngiNerd
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C283 chipset.
|
||||
* Implementation of the OPTi 82C283 chipset.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C291 chipset.
|
||||
|
||||
* Authors: plant/nerd73, Tiseno100
|
||||
* Implementation of the OPTi 82C291 chipset.
|
||||
*
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*
|
||||
*
|
||||
* Authors: plant/nerd73, Tiseno100
|
||||
*
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C391/392 chipset.
|
||||
* Implementation of the OPTi 82C391/392 chipset.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C493/82C495 chipset.
|
||||
* Implementation of the OPTi 82C493/82C495 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C493/82C499 chipset.
|
||||
* Implementation of the OPTi 82C493/82C499 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets.
|
||||
* Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets.
|
||||
|
||||
* Authors: plant/nerd73,
|
||||
* Authors: plant/nerd73,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100
|
||||
*
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2020 plant/nerd73.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -35,7 +35,7 @@
|
||||
typedef struct
|
||||
{
|
||||
uint8_t idx, is_pci,
|
||||
regs[16];
|
||||
regs[16];
|
||||
} opti5x7_t;
|
||||
|
||||
#ifdef ENABLE_OPTI5X7_LOG
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C822 VESA Local Bus to PCI
|
||||
* Bridge Interface.
|
||||
* Implementation of the OPTi 82C822 VESA Local Bus to PCI
|
||||
* Bridge Interface.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2022 Miran Grca.
|
||||
* Copyright 2022 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t irq_convert,
|
||||
pci_regs[256];
|
||||
uint8_t irq_convert,
|
||||
pci_regs[256];
|
||||
} opti822_t;
|
||||
|
||||
// #define ENABLE_OPTI822_LOG 1
|
||||
@@ -56,13 +56,13 @@ opti822_log(const char *fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
if (opti822_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define opti822_log(fmt, ...)
|
||||
# define opti822_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* NOTE: We currently cheat and pass all PCI shadow RAM accesses to ISA as well.
|
||||
@@ -71,13 +71,13 @@ opti822_log(const char *fmt, ...)
|
||||
static void
|
||||
opti822_recalc(opti822_t *dev)
|
||||
{
|
||||
int i, reg, bit_r, bit_w;
|
||||
int state;
|
||||
int i, reg, bit_r, bit_w;
|
||||
int state;
|
||||
uint32_t base;
|
||||
|
||||
for (i = 0; i < 12; i++) {
|
||||
base = 0x000c0000 + (i << 14);
|
||||
reg = 0x44 + ((i >> 2) ^ 3);
|
||||
base = 0x000c0000 + (i << 14);
|
||||
reg = 0x44 + ((i >> 2) ^ 3);
|
||||
bit_w = (i & 3);
|
||||
bit_r = bit_w + 4;
|
||||
bit_w = 1 << bit_w;
|
||||
@@ -99,19 +99,19 @@ static void
|
||||
opti822_update_irqs(opti822_t *dev, int set)
|
||||
{
|
||||
uint8_t val;
|
||||
int i, reg;
|
||||
int shift, irq;
|
||||
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
|
||||
pic_t *temp_pic;
|
||||
int i, reg;
|
||||
int shift, irq;
|
||||
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
|
||||
pic_t *temp_pic;
|
||||
|
||||
// dev->irq_convert = (dev->pci_regs[0x53] & 0x08);
|
||||
dev->irq_convert = 1;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
reg = 0x88 + (i >> 1);
|
||||
reg = 0x88 + (i >> 1);
|
||||
shift = (i & 1) << 2;
|
||||
val = (dev->pci_regs[reg] >> shift) & 0x0f;
|
||||
irq = irq_map[val & 0x07];
|
||||
val = (dev->pci_regs[reg] >> shift) & 0x0f;
|
||||
irq = irq_map[val & 0x07];
|
||||
if (irq == -1)
|
||||
continue;
|
||||
temp_pic = (irq >= 8) ? &pic2 : &pic;
|
||||
@@ -127,8 +127,8 @@ static void
|
||||
opti822_pci_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
opti822_t *dev = (opti822_t *) priv;
|
||||
int irq, irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
|
||||
int pin, slot;
|
||||
int irq, irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
|
||||
int pin, slot;
|
||||
|
||||
opti822_log("opti822_write(%02X, %02X, %02X)\n", func, addr, val);
|
||||
|
||||
@@ -144,7 +144,7 @@ opti822_pci_write(int func, int addr, uint8_t val, void *priv)
|
||||
/* Status Register */
|
||||
case 0x06:
|
||||
if (!(dev->pci_regs[0x52] & 0x04))
|
||||
dev->pci_regs[addr] = (val & 0x80);
|
||||
dev->pci_regs[addr] = (val & 0x80);
|
||||
break;
|
||||
case 0x07:
|
||||
dev->pci_regs[addr] &= ~(val & 0xf9);
|
||||
@@ -293,33 +293,33 @@ opti822_pci_write(int func, int addr, uint8_t val, void *priv)
|
||||
dev->pci_regs[addr] = val;
|
||||
break;
|
||||
|
||||
case 0x88 ... 0x8f:
|
||||
dev->pci_regs[addr] = val;
|
||||
opti822_update_irqs(dev, 0);
|
||||
irq = irq_map[val & 0x07];
|
||||
pin = 4 - ((addr & 0x01) << 1);
|
||||
slot = ((addr & 0x06) >> 1);
|
||||
if (irq >= 0) {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
|
||||
pci_set_irq_routing(pin + (slot << 2), irq);
|
||||
pci_set_irq_level(pin + (slot << 2), !!(val & 0x07));
|
||||
} else {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
|
||||
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
|
||||
}
|
||||
irq = irq_map[(val >> 4) & 0x07];
|
||||
pin = 3 - ((addr & 0x01) << 1);
|
||||
slot = ((addr & 0x06) >> 1);
|
||||
if (irq >= 0) {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
|
||||
pci_set_irq_routing(pin + (slot << 2), irq);
|
||||
pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07));
|
||||
} else {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
|
||||
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
|
||||
}
|
||||
opti822_update_irqs(dev, 1);
|
||||
break;
|
||||
case 0x88 ... 0x8f:
|
||||
dev->pci_regs[addr] = val;
|
||||
opti822_update_irqs(dev, 0);
|
||||
irq = irq_map[val & 0x07];
|
||||
pin = 4 - ((addr & 0x01) << 1);
|
||||
slot = ((addr & 0x06) >> 1);
|
||||
if (irq >= 0) {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
|
||||
pci_set_irq_routing(pin + (slot << 2), irq);
|
||||
pci_set_irq_level(pin + (slot << 2), !!(val & 0x07));
|
||||
} else {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
|
||||
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
|
||||
}
|
||||
irq = irq_map[(val >> 4) & 0x07];
|
||||
pin = 3 - ((addr & 0x01) << 1);
|
||||
slot = ((addr & 0x06) >> 1);
|
||||
if (irq >= 0) {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
|
||||
pci_set_irq_routing(pin + (slot << 2), irq);
|
||||
pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07));
|
||||
} else {
|
||||
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
|
||||
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
|
||||
}
|
||||
opti822_update_irqs(dev, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ static uint8_t
|
||||
opti822_pci_read(int func, int addr, void *priv)
|
||||
{
|
||||
opti822_t *dev = (opti822_t *) priv;
|
||||
uint8_t ret;
|
||||
uint8_t ret;
|
||||
|
||||
ret = 0xff;
|
||||
|
||||
@@ -343,12 +343,14 @@ static void
|
||||
opti822_reset(void *priv)
|
||||
{
|
||||
opti822_t *dev = (opti822_t *) priv;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
memset(dev->pci_regs, 0, 256);
|
||||
|
||||
dev->pci_regs[0x00] = 0x45; dev->pci_regs[0x01] = 0x10; /*OPTi*/
|
||||
dev->pci_regs[0x02] = 0x22; dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/
|
||||
dev->pci_regs[0x00] = 0x45;
|
||||
dev->pci_regs[0x01] = 0x10; /*OPTi*/
|
||||
dev->pci_regs[0x02] = 0x22;
|
||||
dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/
|
||||
dev->pci_regs[0x04] = 0x07;
|
||||
dev->pci_regs[0x06] = 0x80;
|
||||
dev->pci_regs[0x07] = 0x02;
|
||||
@@ -356,7 +358,8 @@ opti822_reset(void *priv)
|
||||
dev->pci_regs[0x0b] = 0x06;
|
||||
dev->pci_regs[0x0d] = 0x20;
|
||||
|
||||
dev->pci_regs[0x40] = 0x01; dev->pci_regs[0x41] = 0x0c;
|
||||
dev->pci_regs[0x40] = 0x01;
|
||||
dev->pci_regs[0x41] = 0x0c;
|
||||
dev->pci_regs[0x43] = 0x02;
|
||||
dev->pci_regs[0x52] = 0x06;
|
||||
dev->pci_regs[0x53] = 0x90;
|
||||
@@ -370,7 +373,7 @@ opti822_reset(void *priv)
|
||||
static void
|
||||
opti822_close(void *p)
|
||||
{
|
||||
opti822_t *dev = (opti822_t *)p;
|
||||
opti822_t *dev = (opti822_t *) p;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the OPTi 82C802G/82C895 chipset.
|
||||
* Implementation of the OPTi 82C802G/82C895 chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2008-2020 Tiseno100.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of VLSI 82C311 ("SCAMP") chipset.
|
||||
* Emulation of VLSI 82C311 ("SCAMP") chipset.
|
||||
*
|
||||
* Note: The datasheet mentions that the chipset supports up to 8MB
|
||||
* of DRAM. This is intepreted as 'being able to refresh up to
|
||||
* 8MB of DRAM chips', because it works fine with bus-based
|
||||
* memory expansion.
|
||||
* Note: The datasheet mentions that the chipset supports up to 8MB
|
||||
* of DRAM. This is intepreted as 'being able to refresh up to
|
||||
* 8MB of DRAM chips', because it works fine with bus-based
|
||||
* memory expansion.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
*
|
||||
* Copyright 2020 Sarah Walker.
|
||||
* Copyright 2020 Sarah Walker.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of Chips&Technology's SCAT (82C235) chipset.
|
||||
* Implementation of Chips&Technology's SCAT (82C235) chipset.
|
||||
*
|
||||
* Re-worked version based on the 82C235 datasheet and errata.
|
||||
* Re-worked version based on the 82C235 datasheet and errata.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Original by GreatPsycho for PCem.
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Authors: Original by GreatPsycho for PCem.
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2017-2019 GreatPsycho.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
* Copyright 2017-2019 GreatPsycho.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the SiS 5511/5512/5513 Pentium PCI/ISA Chipset.
|
||||
* Implementation of the SiS 5511/5512/5513 Pentium PCI/ISA Chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the SiS 5571 Chipset.
|
||||
* Implementation of the SiS 5571 Chipset.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the SiS 85c496/85c497 chip.
|
||||
* Implementation of the SiS 85c496/85c497 chip.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019,2020 Miran Grca.
|
||||
* Copyright 2019-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the SiS 85c401/85c402, 85c460, 85c461, and
|
||||
* 85c407/85c471 chipsets.
|
||||
* Emulation of the SiS 85c401/85c402, 85c460, 85c461, and
|
||||
* 85c407/85c471 chipsets.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019,2020 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019,2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the SiS 85C50x Chipset.
|
||||
* Implementation of the SiS 85C50x Chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020,2021 Tiseno100.
|
||||
* Copyright 2020,2021 Miran Grca.
|
||||
* Copyright 2020-2021 Tiseno100.
|
||||
* Copyright 2020-2021 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the STMicroelectronics STPC series of SoCs.
|
||||
* Implementation of the STMicroelectronics STPC series of SoCs.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
* Authors: RichardG, <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2020 RichardG.
|
||||
* Copyright 2020 RichardG.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the UMC 8886xx PCI to ISA Bridge .
|
||||
* Implementation of the UMC 8886xx PCI to ISA Bridge .
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -65,7 +67,6 @@
|
||||
Function 1 Register 4: (UMC 8886AF/8886BF Only!)
|
||||
Bit 0: Enable Internal IDE
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the UMC HB4 "Super Energy Star Green" PCI Chipset.
|
||||
* Implementation of the UMC HB4 "Super Energy Star Green" PCI Chipset.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Note 2: Additional information were also used from all
|
||||
* around the web.
|
||||
* Note 2: Additional information were also used from all
|
||||
* around the web.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2021 Tiseno100.
|
||||
* Copyright 2021 Miran Grca.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the VIA Apollo series of chips.
|
||||
* Implementation of the VIA Apollo series of chips.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Melissa Goad, <mszoopers@protonmail.com>
|
||||
* Tiseno100,
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Melissa Goad, <mszoopers@protonmail.com>
|
||||
* Tiseno100,
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Melissa Goad.
|
||||
* Copyright 2020 Tiseno100.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Melissa Goad.
|
||||
* Copyright 2020 Tiseno100.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of the VIA PIPC southbridges.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the VIA PIPC southbridges.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Melissa Goad, <mszoopers@protonmail.com>
|
||||
* RichardG, <richardg867@gmail.com>
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Melissa Goad, <mszoopers@protonmail.com>
|
||||
* RichardG, <richardg867@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2020 Melissa Goad.
|
||||
* Copyright 2020-2021 RichardG.
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2020 Melissa Goad.
|
||||
* Copyright 2020-2021 RichardG.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the VIA VT82C49X chipset.
|
||||
* Implementation of the VIA VT82C49X chipset.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Tiseno100.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Tiseno100.
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the VIA VT82C505 VL/PCI Bridge Controller.
|
||||
* Implementation of the VIA VT82C505 VL/PCI Bridge Controller.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Tiseno100,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Tiseno100.
|
||||
* Copyright 2020 Miran Grca.
|
||||
* Copyright 2020 Tiseno100.
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the VLSI VL82c480 chipset.
|
||||
* Implementation of the VLSI VL82c480 chipset.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Western Digital WD76C10 chipset.
|
||||
* Implementation of the Western Digital WD76C10 chipset.
|
||||
*
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
* Note: This chipset has no datasheet, everything were done via
|
||||
* reverse engineering the BIOS of various machines using it.
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*
|
||||
* Authors: Tiseno100
|
||||
*
|
||||
* Copyright 2021 Tiseno100
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
if(DYNAREC)
|
||||
|
||||
@@ -9,28 +9,30 @@
|
||||
#include "x86_ops.h"
|
||||
#include "codegen.h"
|
||||
|
||||
void (*codegen_timing_start)();
|
||||
void (*codegen_timing_start)(void);
|
||||
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
void (*codegen_timing_block_start)();
|
||||
void (*codegen_timing_block_end)();
|
||||
int (*codegen_timing_jump_cycles)();
|
||||
void (*codegen_timing_block_start)(void);
|
||||
void (*codegen_timing_block_end)(void);
|
||||
int (*codegen_timing_jump_cycles)(void);
|
||||
|
||||
void codegen_timing_set(codegen_timing_t *timing)
|
||||
void
|
||||
codegen_timing_set(codegen_timing_t *timing)
|
||||
{
|
||||
codegen_timing_start = timing->start;
|
||||
codegen_timing_prefix = timing->prefix;
|
||||
codegen_timing_opcode = timing->opcode;
|
||||
codegen_timing_block_start = timing->block_start;
|
||||
codegen_timing_block_end = timing->block_end;
|
||||
codegen_timing_jump_cycles = timing->jump_cycles;
|
||||
codegen_timing_start = timing->start;
|
||||
codegen_timing_prefix = timing->prefix;
|
||||
codegen_timing_opcode = timing->opcode;
|
||||
codegen_timing_block_start = timing->block_start;
|
||||
codegen_timing_block_end = timing->block_end;
|
||||
codegen_timing_jump_cycles = timing->jump_cycles;
|
||||
}
|
||||
|
||||
int codegen_in_recompile;
|
||||
|
||||
/* This is for compatibility with new x87 code. */
|
||||
void codegen_set_rounding_mode(int mode)
|
||||
void
|
||||
codegen_set_rounding_mode(int mode)
|
||||
{
|
||||
/* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */
|
||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10);
|
||||
/* cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00); */
|
||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (mode << 10);
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
#include "x86_ops.h"
|
||||
|
||||
#ifdef __amd64__
|
||||
#include "codegen_x86-64.h"
|
||||
# include "codegen_x86-64.h"
|
||||
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86 || defined _M_X64
|
||||
#include "codegen_x86.h"
|
||||
# include "codegen_x86.h"
|
||||
#else
|
||||
#error Dynamic recompiler not implemented on your platform
|
||||
# error Dynamic recompiler not implemented on your platform
|
||||
#endif
|
||||
|
||||
/*Handling self-modifying code (of which there is a lot on x86) :
|
||||
@@ -73,38 +73,37 @@
|
||||
same page).
|
||||
*/
|
||||
|
||||
typedef struct codeblock_t
|
||||
{
|
||||
uint64_t page_mask, page_mask2;
|
||||
uint64_t *dirty_mask, *dirty_mask2;
|
||||
uint64_t cmp;
|
||||
typedef struct codeblock_t {
|
||||
uint64_t page_mask, page_mask2;
|
||||
uint64_t *dirty_mask, *dirty_mask2;
|
||||
uint64_t cmp;
|
||||
|
||||
/*Previous and next pointers, for the codeblock list associated with
|
||||
each physical page. Two sets of pointers, as a codeblock can be
|
||||
present in two pages.*/
|
||||
struct codeblock_t *prev, *next;
|
||||
struct codeblock_t *prev_2, *next_2;
|
||||
/*Previous and next pointers, for the codeblock list associated with
|
||||
each physical page. Two sets of pointers, as a codeblock can be
|
||||
present in two pages.*/
|
||||
struct codeblock_t *prev, *next;
|
||||
struct codeblock_t *prev_2, *next_2;
|
||||
|
||||
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
||||
fails.*/
|
||||
struct codeblock_t *parent, *left, *right;
|
||||
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
||||
fails.*/
|
||||
struct codeblock_t *parent, *left, *right;
|
||||
|
||||
int pnt;
|
||||
int ins;
|
||||
int pnt;
|
||||
int ins;
|
||||
|
||||
int valid;
|
||||
|
||||
int was_recompiled;
|
||||
int TOP;
|
||||
int was_recompiled;
|
||||
int TOP;
|
||||
|
||||
uint32_t pc;
|
||||
uint32_t _cs;
|
||||
uint32_t endpc;
|
||||
uint32_t phys, phys_2;
|
||||
uint32_t status;
|
||||
uint32_t flags;
|
||||
uint32_t pc;
|
||||
uint32_t _cs;
|
||||
uint32_t endpc;
|
||||
uint32_t phys, phys_2;
|
||||
uint32_t status;
|
||||
uint32_t flags;
|
||||
|
||||
uint8_t data[2048];
|
||||
uint8_t data[2048];
|
||||
} codeblock_t;
|
||||
|
||||
/*Code block uses FPU*/
|
||||
@@ -112,219 +111,192 @@ typedef struct codeblock_t
|
||||
/*Code block is always entered with the same FPU top-of-stack*/
|
||||
#define CODEBLOCK_STATIC_TOP 2
|
||||
|
||||
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||
static inline codeblock_t *
|
||||
codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||
{
|
||||
codeblock_t *block = pages[phys >> 12].head;
|
||||
uint64_t a = _cs | ((uint64_t)phys << 32);
|
||||
codeblock_t *block = pages[phys >> 12].head;
|
||||
uint64_t a = _cs | ((uint64_t) phys << 32);
|
||||
|
||||
while (block)
|
||||
{
|
||||
if (a == block->cmp)
|
||||
{
|
||||
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
|
||||
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||
break;
|
||||
}
|
||||
if (a < block->cmp)
|
||||
block = block->left;
|
||||
else
|
||||
block = block->right;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static inline void codeblock_tree_add(codeblock_t *new_block)
|
||||
{
|
||||
codeblock_t *block = pages[new_block->phys >> 12].head;
|
||||
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
|
||||
new_block->cmp = a;
|
||||
|
||||
if (!block)
|
||||
{
|
||||
pages[new_block->phys >> 12].head = new_block;
|
||||
new_block->parent = new_block->left = new_block->right = NULL;
|
||||
while (block) {
|
||||
if (a == block->cmp) {
|
||||
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||
break;
|
||||
}
|
||||
if (a < block->cmp)
|
||||
block = block->left;
|
||||
else
|
||||
{
|
||||
codeblock_t *old_block = NULL;
|
||||
block = block->right;
|
||||
}
|
||||
|
||||
while (block)
|
||||
{
|
||||
old_block = block;
|
||||
if (a < old_block->cmp)
|
||||
block = block->left;
|
||||
else
|
||||
block = block->right;
|
||||
}
|
||||
|
||||
if (a < old_block->cmp)
|
||||
old_block->left = new_block;
|
||||
else
|
||||
old_block->right = new_block;
|
||||
|
||||
new_block->parent = old_block;
|
||||
new_block->left = new_block->right = NULL;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
static inline void codeblock_tree_delete(codeblock_t *block)
|
||||
static inline void
|
||||
codeblock_tree_add(codeblock_t *new_block)
|
||||
{
|
||||
codeblock_t *parent = block->parent;
|
||||
codeblock_t *block = pages[new_block->phys >> 12].head;
|
||||
uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32);
|
||||
new_block->cmp = a;
|
||||
|
||||
if (!block->left && !block->right)
|
||||
{
|
||||
/*Easy case - remove from parent*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = NULL;
|
||||
else
|
||||
{
|
||||
if (parent->left == block)
|
||||
parent->left = NULL;
|
||||
if (parent->right == block)
|
||||
parent->right = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!block->left)
|
||||
{
|
||||
/*Only right node*/
|
||||
if (!parent)
|
||||
{
|
||||
pages[block->phys >> 12].head = block->right;
|
||||
pages[block->phys >> 12].head->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->left == block)
|
||||
{
|
||||
parent->left = block->right;
|
||||
parent->left->parent = parent;
|
||||
}
|
||||
if (parent->right == block)
|
||||
{
|
||||
parent->right = block->right;
|
||||
parent->right->parent = parent;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!block->right)
|
||||
{
|
||||
/*Only left node*/
|
||||
if (!parent)
|
||||
{
|
||||
pages[block->phys >> 12].head = block->left;
|
||||
pages[block->phys >> 12].head->parent = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parent->left == block)
|
||||
{
|
||||
parent->left = block->left;
|
||||
parent->left->parent = parent;
|
||||
}
|
||||
if (parent->right == block)
|
||||
{
|
||||
parent->right = block->left;
|
||||
parent->right->parent = parent;
|
||||
}
|
||||
}
|
||||
return;
|
||||
if (!block) {
|
||||
pages[new_block->phys >> 12].head = new_block;
|
||||
new_block->parent = new_block->left = new_block->right = NULL;
|
||||
} else {
|
||||
codeblock_t *old_block = NULL;
|
||||
|
||||
while (block) {
|
||||
old_block = block;
|
||||
if (a < old_block->cmp)
|
||||
block = block->left;
|
||||
else
|
||||
block = block->right;
|
||||
}
|
||||
|
||||
if (a < old_block->cmp)
|
||||
old_block->left = new_block;
|
||||
else
|
||||
{
|
||||
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
||||
codeblock_t *lowest = block->right, *highest;
|
||||
codeblock_t *old_parent;
|
||||
old_block->right = new_block;
|
||||
|
||||
while (lowest->left)
|
||||
lowest = lowest->left;
|
||||
|
||||
old_parent = lowest->parent;
|
||||
|
||||
/*Replace deleted node with lowest node*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = lowest;
|
||||
else
|
||||
{
|
||||
if (parent->left == block)
|
||||
parent->left = lowest;
|
||||
if (parent->right == block)
|
||||
parent->right = lowest;
|
||||
}
|
||||
|
||||
lowest->parent = parent;
|
||||
lowest->left = block->left;
|
||||
if (lowest->left)
|
||||
lowest->left->parent = lowest;
|
||||
|
||||
old_parent->left = NULL;
|
||||
|
||||
highest = lowest->right;
|
||||
if (!highest)
|
||||
{
|
||||
if (lowest != block->right)
|
||||
{
|
||||
lowest->right = block->right;
|
||||
block->right->parent = lowest;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (highest->right)
|
||||
highest = highest->right;
|
||||
|
||||
if (block->right && block->right != lowest)
|
||||
{
|
||||
highest->right = block->right;
|
||||
block->right->parent = highest;
|
||||
}
|
||||
}
|
||||
new_block->parent = old_block;
|
||||
new_block->left = new_block->right = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define PAGE_MASK_INDEX_MASK 3
|
||||
static inline void
|
||||
codeblock_tree_delete(codeblock_t *block)
|
||||
{
|
||||
codeblock_t *parent = block->parent;
|
||||
|
||||
if (!block->left && !block->right) {
|
||||
/*Easy case - remove from parent*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = NULL;
|
||||
else {
|
||||
if (parent->left == block)
|
||||
parent->left = NULL;
|
||||
if (parent->right == block)
|
||||
parent->right = NULL;
|
||||
}
|
||||
return;
|
||||
} else if (!block->left) {
|
||||
/*Only right node*/
|
||||
if (!parent) {
|
||||
pages[block->phys >> 12].head = block->right;
|
||||
pages[block->phys >> 12].head->parent = NULL;
|
||||
} else {
|
||||
if (parent->left == block) {
|
||||
parent->left = block->right;
|
||||
parent->left->parent = parent;
|
||||
}
|
||||
if (parent->right == block) {
|
||||
parent->right = block->right;
|
||||
parent->right->parent = parent;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (!block->right) {
|
||||
/*Only left node*/
|
||||
if (!parent) {
|
||||
pages[block->phys >> 12].head = block->left;
|
||||
pages[block->phys >> 12].head->parent = NULL;
|
||||
} else {
|
||||
if (parent->left == block) {
|
||||
parent->left = block->left;
|
||||
parent->left->parent = parent;
|
||||
}
|
||||
if (parent->right == block) {
|
||||
parent->right = block->left;
|
||||
parent->right->parent = parent;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
||||
codeblock_t *lowest = block->right, *highest;
|
||||
codeblock_t *old_parent;
|
||||
|
||||
while (lowest->left)
|
||||
lowest = lowest->left;
|
||||
|
||||
old_parent = lowest->parent;
|
||||
|
||||
/*Replace deleted node with lowest node*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = lowest;
|
||||
else {
|
||||
if (parent->left == block)
|
||||
parent->left = lowest;
|
||||
if (parent->right == block)
|
||||
parent->right = lowest;
|
||||
}
|
||||
|
||||
lowest->parent = parent;
|
||||
lowest->left = block->left;
|
||||
if (lowest->left)
|
||||
lowest->left->parent = lowest;
|
||||
|
||||
old_parent->left = NULL;
|
||||
|
||||
highest = lowest->right;
|
||||
if (!highest) {
|
||||
if (lowest != block->right) {
|
||||
lowest->right = block->right;
|
||||
block->right->parent = lowest;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (highest->right)
|
||||
highest = highest->right;
|
||||
|
||||
if (block->right && block->right != lowest) {
|
||||
highest->right = block->right;
|
||||
block->right->parent = highest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PAGE_MASK_INDEX_MASK 3
|
||||
#define PAGE_MASK_INDEX_SHIFT 10
|
||||
#define PAGE_MASK_MASK 63
|
||||
#define PAGE_MASK_SHIFT 4
|
||||
#define PAGE_MASK_MASK 63
|
||||
#define PAGE_MASK_SHIFT 4
|
||||
|
||||
extern codeblock_t *codeblock;
|
||||
|
||||
extern codeblock_t **codeblock_hash;
|
||||
|
||||
void codegen_init();
|
||||
void codegen_reset();
|
||||
void codegen_block_init(uint32_t phys_addr);
|
||||
void codegen_block_remove();
|
||||
void codegen_block_start_recompile(codeblock_t *block);
|
||||
void codegen_block_end_recompile(codeblock_t *block);
|
||||
void codegen_block_end();
|
||||
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
||||
void codegen_generate_seg_restore();
|
||||
void codegen_set_op32();
|
||||
void codegen_flush();
|
||||
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||
extern void codegen_init(void);
|
||||
extern void codegen_reset(void);
|
||||
extern void codegen_block_init(uint32_t phys_addr);
|
||||
extern void codegen_block_remove(void);
|
||||
extern void codegen_block_start_recompile(codeblock_t *block);
|
||||
extern void codegen_block_end_recompile(codeblock_t *block);
|
||||
extern void codegen_block_end(void);
|
||||
extern void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
||||
extern void codegen_generate_seg_restore(void);
|
||||
extern void codegen_set_op32(void);
|
||||
extern void codegen_flush(void);
|
||||
extern void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||
|
||||
extern int cpu_block_end;
|
||||
extern int cpu_block_end;
|
||||
extern uint32_t codegen_endpc;
|
||||
|
||||
extern int codegen_block_cycles;
|
||||
|
||||
extern void (*codegen_timing_start)();
|
||||
extern void (*codegen_timing_start)(void);
|
||||
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
extern void (*codegen_timing_block_start)();
|
||||
extern void (*codegen_timing_block_end)();
|
||||
extern int (*codegen_timing_jump_cycles)();
|
||||
extern void (*codegen_timing_block_start)(void);
|
||||
extern void (*codegen_timing_block_end)(void);
|
||||
extern int (*codegen_timing_jump_cycles)(void);
|
||||
|
||||
typedef struct codegen_timing_t
|
||||
{
|
||||
void (*start)();
|
||||
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
void (*block_start)();
|
||||
void (*block_end)();
|
||||
int (*jump_cycles)();
|
||||
typedef struct codegen_timing_t {
|
||||
void (*start)(void);
|
||||
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
void (*block_start)(void);
|
||||
void (*block_end)(void);
|
||||
int (*jump_cycles)(void);
|
||||
} codegen_timing_t;
|
||||
|
||||
extern codegen_timing_t codegen_timing_pentium;
|
||||
@@ -342,53 +314,53 @@ extern int block_pos;
|
||||
|
||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
||||
|
||||
static inline void addbyte(uint8_t val)
|
||||
static inline void
|
||||
addbyte(uint8_t val)
|
||||
{
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX) {
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addword(uint16_t val)
|
||||
static inline void
|
||||
addword(uint16_t val)
|
||||
{
|
||||
uint16_t *p = (uint16_t *) &codeblock[block_current].data[block_pos];
|
||||
*p = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
*p = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX) {
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addlong(uint32_t val)
|
||||
static inline void
|
||||
addlong(uint32_t val)
|
||||
{
|
||||
uint32_t *p = (uint32_t *) &codeblock[block_current].data[block_pos];
|
||||
*p = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
*p = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX) {
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addquad(uint64_t val)
|
||||
static inline void
|
||||
addquad(uint64_t val)
|
||||
{
|
||||
uint64_t *p = (uint64_t *) &codeblock[block_current].data[block_pos];
|
||||
*p = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
*p = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX) {
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
|
||||
extern uint32_t recomp_page;
|
||||
|
||||
extern x86seg *op_ea_seg;
|
||||
extern int op_ssegs;
|
||||
extern x86seg *op_ea_seg;
|
||||
extern int op_ssegs;
|
||||
extern uint32_t op_old_pc;
|
||||
|
||||
/*Set to 1 if flags have been changed in the block being recompiled, and hence
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
enum
|
||||
{
|
||||
ACCREG_cycles = 0,
|
||||
enum {
|
||||
ACCREG_cycles = 0,
|
||||
|
||||
ACCREG_COUNT
|
||||
ACCREG_COUNT
|
||||
};
|
||||
|
||||
struct ir_data_t;
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta);
|
||||
void codegen_accumulate_flush(void);
|
||||
void codegen_accumulate_reset();
|
||||
void codegen_accumulate_reset(void);
|
||||
|
||||
@@ -9,59 +9,61 @@
|
||||
|
||||
static struct
|
||||
{
|
||||
int count;
|
||||
uintptr_t dest_reg;
|
||||
} acc_regs[] =
|
||||
{
|
||||
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)},
|
||||
int count;
|
||||
uintptr_t dest_reg;
|
||||
} acc_regs[] = {
|
||||
[ACCREG_cycles] = {0, (uintptr_t) & (cycles)},
|
||||
};
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta)
|
||||
void
|
||||
codegen_accumulate(int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
#ifdef USE_ACYCS
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
if (delta == -1) {
|
||||
/* -delta = 1 */
|
||||
addbyte(0xff); /*inc dword ptr[&acycs]*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
} else if (delta == 1) {
|
||||
/* -delta = -1 */
|
||||
addbyte(0xff); /*dec dword ptr[&acycs]*/
|
||||
addbyte(0x0c);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
} else {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
addlong(-delta);
|
||||
}
|
||||
}
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
if (delta == -1) {
|
||||
/* -delta = 1 */
|
||||
addbyte(0xff); /*inc dword ptr[&acycs]*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
} else if (delta == 1) {
|
||||
/* -delta = -1 */
|
||||
addbyte(0xff); /*dec dword ptr[&acycs]*/
|
||||
addbyte(0x0c);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
} else {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x25);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
addlong(-delta);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(void)
|
||||
void
|
||||
codegen_accumulate_flush(void)
|
||||
{
|
||||
if (acc_regs[0].count) {
|
||||
/* To reduce the size of the generated code, we take advantage of
|
||||
the fact that the target offset points to _cycles within cpu_state,
|
||||
so we can just use our existing infrastracture for variables
|
||||
relative to cpu_state. */
|
||||
addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/
|
||||
addbyte(0x45);
|
||||
addbyte((uint8_t)cpu_state_offset(_cycles));
|
||||
addlong(acc_regs[0].count);
|
||||
}
|
||||
if (acc_regs[0].count) {
|
||||
/* To reduce the size of the generated code, we take advantage of
|
||||
the fact that the target offset points to _cycles within cpu_state,
|
||||
so we can just use our existing infrastracture for variables
|
||||
relative to cpu_state. */
|
||||
addbyte(0x81); /*ADDL $acc_regs[0].count,(_cycles)*/
|
||||
addbyte(0x45);
|
||||
addbyte((uint8_t) cpu_state_offset(_cycles));
|
||||
addlong(acc_regs[0].count);
|
||||
}
|
||||
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
void codegen_accumulate_reset()
|
||||
void
|
||||
codegen_accumulate_reset(void)
|
||||
{
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
@@ -9,56 +9,58 @@
|
||||
|
||||
static struct
|
||||
{
|
||||
int count;
|
||||
uintptr_t dest_reg;
|
||||
} acc_regs[] =
|
||||
{
|
||||
[ACCREG_cycles] = {0, (uintptr_t) &(cycles)}
|
||||
int count;
|
||||
uintptr_t dest_reg;
|
||||
} acc_regs[] = {
|
||||
[ACCREG_cycles] = {0, (uintptr_t) & (cycles)}
|
||||
};
|
||||
|
||||
void codegen_accumulate(int acc_reg, int delta)
|
||||
void
|
||||
codegen_accumulate(int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
#ifdef USE_ACYCS
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
if (delta == -1) {
|
||||
/* -delta = 1 */
|
||||
addbyte(0xff); /*inc dword ptr[&acycs]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
} else if (delta == 1) {
|
||||
/* -delta = -1 */
|
||||
addbyte(0xff); /*dec dword ptr[&acycs]*/
|
||||
addbyte(0x0d);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
} else {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t) (uintptr_t) &(acycs));
|
||||
addlong((uintptr_t) -delta);
|
||||
}
|
||||
}
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
if (delta == -1) {
|
||||
/* -delta = 1 */
|
||||
addbyte(0xff); /*inc dword ptr[&acycs]*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
} else if (delta == 1) {
|
||||
/* -delta = -1 */
|
||||
addbyte(0xff); /*dec dword ptr[&acycs]*/
|
||||
addbyte(0x0d);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
} else {
|
||||
addbyte(0x81); /*ADD $acc_regs[c].count,acc_regs[c].dest*/
|
||||
addbyte(0x05);
|
||||
addlong((uint32_t) (uintptr_t) & (acycs));
|
||||
addlong((uintptr_t) -delta);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(void)
|
||||
void
|
||||
codegen_accumulate_flush(void)
|
||||
{
|
||||
if (acc_regs[0].count) {
|
||||
/* To reduce the size of the generated code, we take advantage of
|
||||
the fact that the target offset points to _cycles within cpu_state,
|
||||
so we can just use our existing infrastracture for variables
|
||||
relative to cpu_state. */
|
||||
addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/
|
||||
addbyte(0x45);
|
||||
addbyte((uint8_t)cpu_state_offset(_cycles));
|
||||
addlong(acc_regs[0].count);
|
||||
}
|
||||
if (acc_regs[0].count) {
|
||||
/* To reduce the size of the generated code, we take advantage of
|
||||
the fact that the target offset points to _cycles within cpu_state,
|
||||
so we can just use our existing infrastracture for variables
|
||||
relative to cpu_state. */
|
||||
addbyte(0x81); /*MOVL $acc_regs[0].count,(_cycles)*/
|
||||
addbyte(0x45);
|
||||
addbyte((uint8_t) cpu_state_offset(_cycles));
|
||||
addlong(acc_regs[0].count);
|
||||
}
|
||||
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
void codegen_accumulate_reset()
|
||||
void
|
||||
codegen_accumulate_reset(void)
|
||||
{
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
#include "codegen_ops.h"
|
||||
|
||||
#if defined __amd64__ || defined _M_X64
|
||||
#include "codegen_ops_x86-64.h"
|
||||
# include "codegen_ops_x86-64.h"
|
||||
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
|
||||
#include "codegen_ops_x86.h"
|
||||
# include "codegen_ops_x86.h"
|
||||
#endif
|
||||
|
||||
#include "codegen_ops_arith.h"
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "codegen_ops_stack.h"
|
||||
#include "codegen_ops_xchg.h"
|
||||
|
||||
RecompOpFn recomp_opcodes[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
|
||||
@@ -77,10 +77,11 @@ RecompOpFn recomp_opcodes[512] =
|
||||
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_0f[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_0f[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -124,11 +125,11 @@ RecompOpFn recomp_opcodes_0f[512] =
|
||||
/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
|
||||
/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
|
||||
/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
RecompOpFn recomp_opcodes_d8[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_d8[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
|
||||
@@ -172,10 +173,11 @@ RecompOpFn recomp_opcodes_d8[512] =
|
||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
||||
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
|
||||
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_d9[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_d9[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -219,10 +221,11 @@ RecompOpFn recomp_opcodes_d9[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_da[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_da[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
|
||||
@@ -266,10 +269,11 @@ RecompOpFn recomp_opcodes_da[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_db[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_db[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -313,10 +317,11 @@ RecompOpFn recomp_opcodes_db[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_dc[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_dc[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
|
||||
@@ -360,10 +365,11 @@ RecompOpFn recomp_opcodes_dc[512] =
|
||||
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
|
||||
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
|
||||
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_dd[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_dd[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -407,10 +413,11 @@ RecompOpFn recomp_opcodes_dd[512] =
|
||||
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_de[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_de[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
|
||||
@@ -454,10 +461,11 @@ RecompOpFn recomp_opcodes_de[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
|
||||
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_df[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_df[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -501,10 +509,11 @@ RecompOpFn recomp_opcodes_df[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_REPE[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_REPE[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -548,10 +557,11 @@ RecompOpFn recomp_opcodes_REPE[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
RecompOpFn recomp_opcodes_REPNE[512] =
|
||||
{
|
||||
RecompOpFn recomp_opcodes_REPNE[512] = {
|
||||
// clang-format off
|
||||
/*16-bit data*/
|
||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -595,4 +605,5 @@ RecompOpFn recomp_opcodes_REPNE[512] =
|
||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -26,21 +26,21 @@ extern RecompOpFn recomp_opcodes_REPNE[512];
|
||||
#define REG_EBP 5
|
||||
#define REG_ESI 6
|
||||
#define REG_EDI 7
|
||||
#define REG_AX 0
|
||||
#define REG_CX 1
|
||||
#define REG_DX 2
|
||||
#define REG_BX 3
|
||||
#define REG_SP 4
|
||||
#define REG_BP 5
|
||||
#define REG_SI 6
|
||||
#define REG_DI 7
|
||||
#define REG_AL 0
|
||||
#define REG_AH 4
|
||||
#define REG_CL 1
|
||||
#define REG_CH 5
|
||||
#define REG_DL 2
|
||||
#define REG_DH 6
|
||||
#define REG_BL 3
|
||||
#define REG_BH 7
|
||||
#define REG_AX 0
|
||||
#define REG_CX 1
|
||||
#define REG_DX 2
|
||||
#define REG_BX 3
|
||||
#define REG_SP 4
|
||||
#define REG_BP 5
|
||||
#define REG_SI 6
|
||||
#define REG_DI 7
|
||||
#define REG_AL 0
|
||||
#define REG_AH 4
|
||||
#define REG_CL 1
|
||||
#define REG_CH 5
|
||||
#define REG_DL 2
|
||||
#define REG_DH 6
|
||||
#define REG_BL 3
|
||||
#define REG_BH 7
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,256 +1,268 @@
|
||||
static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_ENTER();
|
||||
|
||||
FP_FXCH(opcode & 7);
|
||||
FP_FXCH(opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_ENTER();
|
||||
|
||||
FP_FLD(opcode & 7);
|
||||
FP_FLD(opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_ENTER();
|
||||
|
||||
FP_FST(opcode & 7);
|
||||
FP_FST(opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_ENTER();
|
||||
|
||||
FP_FST(opcode & 7);
|
||||
FP_POP();
|
||||
FP_FST(opcode & 7);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
|
||||
FP_LOAD_S();
|
||||
FP_LOAD_S();
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
|
||||
FP_LOAD_D();
|
||||
FP_LOAD_D();
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
|
||||
FP_LOAD_IW();
|
||||
FP_LOAD_IW();
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
|
||||
FP_LOAD_IL();
|
||||
FP_LOAD_IL();
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
|
||||
FP_LOAD_IQ();
|
||||
FP_LOAD_IQ();
|
||||
|
||||
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
|
||||
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
host_reg = FP_LOAD_REG(0);
|
||||
host_reg = FP_LOAD_REG(0);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg1, host_reg2 = 0;
|
||||
x86seg *target_seg;
|
||||
int host_reg1, host_reg2 = 0;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
|
||||
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 7);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 7);
|
||||
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
|
||||
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
|
||||
|
||||
FP_POP();
|
||||
FP_POP();
|
||||
|
||||
return new_pc;
|
||||
return new_pc;
|
||||
}
|
||||
static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
|
||||
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
|
||||
|
||||
FP_POP();
|
||||
FP_POP();
|
||||
|
||||
return new_pc;
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
#define ropFarith(name, size, load, op) \
|
||||
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
x86seg *target_seg; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
op_pc--; \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
\
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
load(target_seg); \
|
||||
\
|
||||
op(FPU_ ## name); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
}
|
||||
#define ropFarith(name, size, load, op) \
|
||||
static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
x86seg *target_seg; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
op_pc--; \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
\
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
load(target_seg); \
|
||||
\
|
||||
op(FPU_##name); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
}
|
||||
|
||||
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
|
||||
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
|
||||
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
|
||||
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
|
||||
|
||||
#define ropFcompare(name, size, load, op) \
|
||||
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
x86seg *target_seg; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
op_pc--; \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
\
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
load(target_seg); \
|
||||
\
|
||||
op(); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \
|
||||
\
|
||||
FP_POP(); \
|
||||
\
|
||||
return new_pc; \
|
||||
}
|
||||
#define ropFcompare(name, size, load, op) \
|
||||
static uint32_t ropF##name##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
x86seg *target_seg; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
op_pc--; \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
\
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
load(target_seg); \
|
||||
\
|
||||
op(); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t ropF##name##P##size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t new_pc = ropF##name##size(opcode, fetchdat, op_32, op_pc, block); \
|
||||
\
|
||||
FP_POP(); \
|
||||
\
|
||||
return new_pc; \
|
||||
}
|
||||
|
||||
ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S);
|
||||
ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D);
|
||||
@@ -326,320 +338,346 @@ static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint
|
||||
return op_pc + 1;
|
||||
}*/
|
||||
|
||||
|
||||
static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_ADD, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, opcode & 7);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, opcode & 7);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIV, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_MUL, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUB, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
||||
FP_POP();
|
||||
FP_ENTER();
|
||||
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
|
||||
FP_POP();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, 1);
|
||||
FP_POP2();
|
||||
FP_ENTER();
|
||||
FP_COMPARE_REG(0, 1);
|
||||
FP_POP2();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
FP_ENTER();
|
||||
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
|
||||
FP_ENTER();
|
||||
host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxs);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
host_reg = FP_LOAD_REG_INT_W(0);
|
||||
host_reg = FP_LOAD_REG_INT_W(0);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
host_reg = FP_LOAD_REG_INT(0);
|
||||
host_reg = FP_LOAD_REG_INT(0);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
|
||||
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
|
||||
|
||||
FP_POP();
|
||||
FP_POP();
|
||||
|
||||
return new_pc;
|
||||
return new_pc;
|
||||
}
|
||||
static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
|
||||
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
|
||||
|
||||
FP_POP();
|
||||
FP_POP();
|
||||
|
||||
return new_pc;
|
||||
return new_pc;
|
||||
}
|
||||
static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
int host_reg1, host_reg2;
|
||||
x86seg *target_seg;
|
||||
int host_reg1, host_reg2;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
|
||||
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
|
||||
FP_POP();
|
||||
FP_POP();
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
|
||||
UPDATE_NPXC(0);
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.npxc, 0);
|
||||
UPDATE_NPXC(0);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
x86seg *target_seg;
|
||||
int host_reg;
|
||||
x86seg *target_seg;
|
||||
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
FP_ENTER();
|
||||
op_pc--;
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
|
||||
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
host_reg = LOAD_VAR_W((uintptr_t) &cpu_state.npxc);
|
||||
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_FCHS();
|
||||
FP_ENTER();
|
||||
FP_FCHS();
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
#define opFLDimm(name, v) \
|
||||
static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
static double fp_imm = v; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
#define opFLDimm(name, v) \
|
||||
static uint32_t ropFLD##name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
static double fp_imm = v; \
|
||||
\
|
||||
FP_ENTER(); \
|
||||
FP_LOAD_IMM_Q(*(uint64_t *) &fp_imm); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
opFLDimm(1, 1.0)
|
||||
opFLDimm(L2T, 3.3219280948873623)
|
||||
opFLDimm(L2E, 1.4426950408889634);
|
||||
opFLDimm(L2T, 3.3219280948873623)
|
||||
opFLDimm(L2E, 1.4426950408889634);
|
||||
opFLDimm(PI, 3.141592653589793);
|
||||
opFLDimm(EG2, 0.3010299956639812);
|
||||
opFLDimm(Z, 0.0)
|
||||
|
||||
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
FP_ENTER();
|
||||
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
|
||||
FP_ENTER();
|
||||
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
@@ -1,257 +1,258 @@
|
||||
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 1 + offset);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t offset = fastreadl(cs + op_pc);
|
||||
uint32_t offset = fastreadl(cs + op_pc);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_ECX);
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_CX);
|
||||
TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
|
||||
}
|
||||
if (op_32 & 0x200) {
|
||||
int host_reg = LOAD_REG_L(REG_ECX);
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc + 1 + offset, 0);
|
||||
} else {
|
||||
int host_reg = LOAD_REG_W(REG_CX);
|
||||
TEST_ZERO_JUMP_W(host_reg, op_pc + 1 + offset, 0);
|
||||
}
|
||||
|
||||
return op_pc+1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
uint32_t offset = fetchdat & 0xff;
|
||||
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
if (offset & 0x80)
|
||||
offset |= 0xffffff00;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(REG_ECX);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
int host_reg = LOAD_REG_W(REG_CX);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
|
||||
}
|
||||
if (op_32 & 0x200) {
|
||||
int host_reg = LOAD_REG_L(REG_ECX);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc + 1 + offset, 0);
|
||||
} else {
|
||||
int host_reg = LOAD_REG_W(REG_CX);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
TEST_NONZERO_JUMP_W(host_reg, op_pc + 1 + offset, 0);
|
||||
}
|
||||
|
||||
return op_pc+1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
||||
static void
|
||||
BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
|
||||
{
|
||||
CALL_FUNC((uintptr_t)CF_SET);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
CALL_FUNC((uintptr_t) CF_SET);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
}
|
||||
|
||||
static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
||||
static void
|
||||
BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC8:
|
||||
case FLAGS_DEC16:
|
||||
case FLAGS_DEC32:
|
||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
||||
if (not)
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) {
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC8:
|
||||
case FLAGS_DEC16:
|
||||
case FLAGS_DEC32:
|
||||
host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res);
|
||||
if (not )
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
CALL_FUNC((uintptr_t)ZF_SET);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
}
|
||||
case FLAGS_UNKNOWN:
|
||||
CALL_FUNC((uintptr_t) ZF_SET);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
||||
static void
|
||||
BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
|
||||
{
|
||||
CALL_FUNC((uintptr_t)VF_SET);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
CALL_FUNC((uintptr_t) VF_SET);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
}
|
||||
|
||||
static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
||||
static void
|
||||
BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
|
||||
{
|
||||
CALL_FUNC((uintptr_t)PF_SET);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
CALL_FUNC((uintptr_t) PF_SET);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
}
|
||||
|
||||
static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
|
||||
static void
|
||||
BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not )
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
|
||||
{
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_DEC8:
|
||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x80);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN) {
|
||||
case FLAGS_ZN8:
|
||||
case FLAGS_ADD8:
|
||||
case FLAGS_SUB8:
|
||||
case FLAGS_SHL8:
|
||||
case FLAGS_SHR8:
|
||||
case FLAGS_SAR8:
|
||||
case FLAGS_INC8:
|
||||
case FLAGS_DEC8:
|
||||
host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x80);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_DEC16:
|
||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x8000);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
case FLAGS_ZN16:
|
||||
case FLAGS_ADD16:
|
||||
case FLAGS_SUB16:
|
||||
case FLAGS_SHL16:
|
||||
case FLAGS_SHR16:
|
||||
case FLAGS_SAR16:
|
||||
case FLAGS_INC16:
|
||||
case FLAGS_DEC16:
|
||||
host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x8000);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC32:
|
||||
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x80000000);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
case FLAGS_ZN32:
|
||||
case FLAGS_ADD32:
|
||||
case FLAGS_SUB32:
|
||||
case FLAGS_SHL32:
|
||||
case FLAGS_SHR32:
|
||||
case FLAGS_SAR32:
|
||||
case FLAGS_INC32:
|
||||
case FLAGS_DEC32:
|
||||
host_reg = LOAD_VAR_L((uintptr_t) &cpu_state.flags_res);
|
||||
AND_HOST_REG_IMM(host_reg, 0x80000000);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(host_reg, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
|
||||
case FLAGS_UNKNOWN:
|
||||
CALL_FUNC((uintptr_t)NF_SET);
|
||||
if (not)
|
||||
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
|
||||
break;
|
||||
}
|
||||
case FLAGS_UNKNOWN:
|
||||
CALL_FUNC((uintptr_t) NF_SET);
|
||||
if (not )
|
||||
TEST_ZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
else
|
||||
TEST_NONZERO_JUMP_L(0, op_pc + pc_offset + offset, timing_bt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define ropBRANCH(name, func, not ) \
|
||||
static uint32_t rop##name(uint8_t opcode, uint32_t fetchdat, \
|
||||
uint32_t op_32, uint32_t op_pc, \
|
||||
codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fetchdat & 0xff; \
|
||||
\
|
||||
if (offset & 0x80) \
|
||||
offset |= 0xffffff00; \
|
||||
\
|
||||
func(1, op_pc, offset, not ); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
} \
|
||||
static uint32_t rop##name##_w(uint8_t opcode, \
|
||||
uint32_t fetchdat, uint32_t op_32, \
|
||||
uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fetchdat & 0xffff; \
|
||||
\
|
||||
if (offset & 0x8000) \
|
||||
offset |= 0xffff0000; \
|
||||
\
|
||||
func(2, op_pc, offset, not ); \
|
||||
\
|
||||
return op_pc + 2; \
|
||||
} \
|
||||
static uint32_t rop##name##_l(uint8_t opcode, \
|
||||
uint32_t fetchdat, uint32_t op_32, \
|
||||
uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fastreadl(cs + op_pc); \
|
||||
\
|
||||
func(4, op_pc, offset, not ); \
|
||||
\
|
||||
return op_pc + 4; \
|
||||
}
|
||||
|
||||
#define ropBRANCH(name, func, not) \
|
||||
static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \
|
||||
uint32_t op_32, uint32_t op_pc, \
|
||||
codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fetchdat & 0xff; \
|
||||
\
|
||||
if (offset & 0x80) \
|
||||
offset |= 0xffffff00; \
|
||||
\
|
||||
func(1, op_pc, offset, not); \
|
||||
\
|
||||
return op_pc+1; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _w(uint8_t opcode, \
|
||||
uint32_t fetchdat, uint32_t op_32, \
|
||||
uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fetchdat & 0xffff; \
|
||||
\
|
||||
if (offset & 0x8000) \
|
||||
offset |= 0xffff0000; \
|
||||
\
|
||||
func(2, op_pc, offset, not); \
|
||||
\
|
||||
return op_pc+2; \
|
||||
} \
|
||||
static uint32_t rop ## name ## _l(uint8_t opcode, \
|
||||
uint32_t fetchdat, uint32_t op_32, \
|
||||
uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
uint32_t offset = fastreadl(cs + op_pc); \
|
||||
\
|
||||
func(4, op_pc, offset, not); \
|
||||
\
|
||||
return op_pc+4; \
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
ropBRANCH(JB, BRANCH_COND_B, 0)
|
||||
ropBRANCH(JNB, BRANCH_COND_B, 1)
|
||||
ropBRANCH(JE, BRANCH_COND_E, 0)
|
||||
@@ -268,3 +269,4 @@ ropBRANCH(JLE, BRANCH_COND_LE, 0)
|
||||
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
|
||||
ropBRANCH(JBE, BRANCH_COND_BE, 0)
|
||||
ropBRANCH(JNBE, BRANCH_COND_BE, 1)
|
||||
// clang-format on
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,272 +1,263 @@
|
||||
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
CLEAR_BITS((uintptr_t)&cpu_state.flags, D_FLAG);
|
||||
return op_pc;
|
||||
CLEAR_BITS((uintptr_t) &cpu_state.flags, D_FLAG);
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
SET_BITS((uintptr_t)&cpu_state.flags, D_FLAG);
|
||||
return op_pc;
|
||||
SET_BITS((uintptr_t) &cpu_state.flags, D_FLAG);
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||
return 0;
|
||||
CLEAR_BITS((uintptr_t)&cpu_state.flags, I_FLAG);
|
||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||
return 0;
|
||||
CLEAR_BITS((uintptr_t) &cpu_state.flags, I_FLAG);
|
||||
#ifdef CHECK_INT
|
||||
CLEAR_BITS((uintptr_t)&pic_pending, 0xffffffff);
|
||||
CLEAR_BITS((uintptr_t) &pic_pending, 0xffffffff);
|
||||
#endif
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||
return 0;
|
||||
SET_BITS((uintptr_t)&cpu_state.flags, I_FLAG);
|
||||
return op_pc;
|
||||
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
|
||||
return 0;
|
||||
SET_BITS((uintptr_t) &cpu_state.flags, I_FLAG);
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
return 0;
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
return 0;
|
||||
|
||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
||||
CALL_FUNC((uintptr_t) flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_B(fetchdat & 7);
|
||||
else {
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
|
||||
}
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8);
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8);
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
}
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC8);
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_B(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC8);
|
||||
STORE_HOST_REG_ADDR_BL((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_B_RELEASE(host_reg);
|
||||
else {
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t codegen_temp;
|
||||
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
{
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
host_reg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_W(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16);
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16);
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
|
||||
host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp);
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x20: /*JMP*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x30: /*PUSH*/
|
||||
if (!host_reg)
|
||||
host_reg = LOAD_HOST_REG(host_reg);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
return op_pc + 1;
|
||||
}
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC((uintptr_t) flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_W(fetchdat & 7);
|
||||
else {
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00) {
|
||||
MEM_LOAD_ADDR_EA_W(target_seg);
|
||||
host_reg = 0;
|
||||
} else {
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_W(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC16);
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else {
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM_W(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC16);
|
||||
STORE_HOST_REG_ADDR_WL((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_W_RELEASE(host_reg);
|
||||
else {
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
|
||||
host_reg = LOAD_VAR_W((uintptr_t) &codegen_temp);
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t) &cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x20: /*JMP*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x30: /*PUSH*/
|
||||
if (!host_reg)
|
||||
host_reg = LOAD_HOST_REG(host_reg);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
return op_pc + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int host_reg;
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC((uintptr_t)flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
else
|
||||
{
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00)
|
||||
{
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
host_reg = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_L(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else
|
||||
{
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
|
||||
host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x20: /*JMP*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x30: /*PUSH*/
|
||||
if (!host_reg)
|
||||
host_reg = LOAD_HOST_REG(host_reg);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
return op_pc + 1;
|
||||
}
|
||||
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
|
||||
return 0;
|
||||
|
||||
if ((fetchdat & 0x30) == 0x00)
|
||||
CALL_FUNC((uintptr_t) flags_rebuild_c);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
else {
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
if ((fetchdat & 0x30) != 0x00) {
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
host_reg = 0;
|
||||
} else {
|
||||
SAVE_EA();
|
||||
MEM_CHECK_WRITE_L(target_seg);
|
||||
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
|
||||
}
|
||||
}
|
||||
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x00: /*INC*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
ADD_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_INC32);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else {
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
case 0x08: /*DEC*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_op1, host_reg);
|
||||
SUB_HOST_REG_IMM(host_reg, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, 1);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_DEC32);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.flags_res, host_reg);
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
STORE_REG_L_RELEASE(host_reg);
|
||||
else {
|
||||
LOAD_EA();
|
||||
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
|
||||
}
|
||||
codegen_flags_changed = 1;
|
||||
return op_pc + 1;
|
||||
|
||||
case 0x10: /*CALL*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, host_reg);
|
||||
RELEASE_REG(host_reg);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 1);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
|
||||
host_reg = LOAD_VAR_L((uintptr_t) &codegen_temp);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x20: /*JMP*/
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, host_reg);
|
||||
return -1;
|
||||
|
||||
case 0x30: /*PUSH*/
|
||||
if (!host_reg)
|
||||
host_reg = LOAD_HOST_REG(host_reg);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
return op_pc + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,277 +1,267 @@
|
||||
static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg1, host_reg2 = 0;
|
||||
int host_reg1, host_reg2 = 0;
|
||||
|
||||
MMX_ENTER();
|
||||
MMX_ENTER();
|
||||
|
||||
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
|
||||
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
if ((fetchdat & 0xc0) == 0xc0) {
|
||||
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
|
||||
} else {
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 7);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 7);
|
||||
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
}
|
||||
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
MMX_ENTER();
|
||||
MMX_ENTER();
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg1, host_reg2;
|
||||
if ((fetchdat & 0xc0) == 0xc0) {
|
||||
int host_reg1, host_reg2;
|
||||
|
||||
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
|
||||
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
|
||||
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
|
||||
} else {
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
|
||||
}
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg);
|
||||
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
MMX_ENTER();
|
||||
MMX_ENTER();
|
||||
|
||||
host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
|
||||
host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
if ((fetchdat & 0xc0) == 0xc0) {
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
|
||||
} else {
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 3);
|
||||
CHECK_SEG_WRITE(target_seg);
|
||||
CHECK_SEG_LIMITS(target_seg, 3);
|
||||
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
}
|
||||
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
MMX_ENTER();
|
||||
MMX_ENTER();
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
if ((fetchdat & 0xc0) == 0xc0) {
|
||||
int host_reg = LOAD_REG_L(fetchdat & 7);
|
||||
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
|
||||
} else {
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
|
||||
CHECK_SEG_READ(target_seg);
|
||||
CHECK_SEG_READ(target_seg);
|
||||
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
|
||||
}
|
||||
MEM_LOAD_ADDR_EA_L(target_seg);
|
||||
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
#define MMX_OP(name, func) \
|
||||
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int src_reg1, src_reg2; \
|
||||
int xmm_src, xmm_dst; \
|
||||
\
|
||||
MMX_ENTER(); \
|
||||
\
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) { \
|
||||
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
|
||||
} else { \
|
||||
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
\
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
CHECK_SEG_READ(target_seg); \
|
||||
\
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg); \
|
||||
src_reg1 = LOAD_Q_REG_1; \
|
||||
src_reg2 = LOAD_Q_REG_2; \
|
||||
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
|
||||
MEM_LOAD_ADDR_EA_Q(target_seg); \
|
||||
src_reg1 = LOAD_Q_REG_1; \
|
||||
src_reg2 = LOAD_Q_REG_2; \
|
||||
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
|
||||
} \
|
||||
xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \
|
||||
func(xmm_dst, xmm_src); \
|
||||
func(xmm_dst, xmm_src); \
|
||||
STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \
|
||||
\
|
||||
return op_pc + 1; \
|
||||
}
|
||||
}
|
||||
|
||||
MMX_OP(ropPAND, MMX_AND)
|
||||
MMX_OP(ropPAND, MMX_AND)
|
||||
MMX_OP(ropPANDN, MMX_ANDN)
|
||||
MMX_OP(ropPOR, MMX_OR)
|
||||
MMX_OP(ropPXOR, MMX_XOR)
|
||||
MMX_OP(ropPOR, MMX_OR)
|
||||
MMX_OP(ropPXOR, MMX_XOR)
|
||||
|
||||
MMX_OP(ropPADDB, MMX_ADDB)
|
||||
MMX_OP(ropPADDW, MMX_ADDW)
|
||||
MMX_OP(ropPADDD, MMX_ADDD)
|
||||
MMX_OP(ropPADDSB, MMX_ADDSB)
|
||||
MMX_OP(ropPADDSW, MMX_ADDSW)
|
||||
MMX_OP(ropPADDUSB, MMX_ADDUSB)
|
||||
MMX_OP(ropPADDUSW, MMX_ADDUSW)
|
||||
MMX_OP(ropPADDB, MMX_ADDB)
|
||||
MMX_OP(ropPADDW, MMX_ADDW)
|
||||
MMX_OP(ropPADDD, MMX_ADDD)
|
||||
MMX_OP(ropPADDSB, MMX_ADDSB)
|
||||
MMX_OP(ropPADDSW, MMX_ADDSW)
|
||||
MMX_OP(ropPADDUSB, MMX_ADDUSB)
|
||||
MMX_OP(ropPADDUSW, MMX_ADDUSW)
|
||||
|
||||
MMX_OP(ropPSUBB, MMX_SUBB)
|
||||
MMX_OP(ropPSUBW, MMX_SUBW)
|
||||
MMX_OP(ropPSUBD, MMX_SUBD)
|
||||
MMX_OP(ropPSUBSB, MMX_SUBSB)
|
||||
MMX_OP(ropPSUBSW, MMX_SUBSW)
|
||||
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
|
||||
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
|
||||
MMX_OP(ropPSUBB, MMX_SUBB)
|
||||
MMX_OP(ropPSUBW, MMX_SUBW)
|
||||
MMX_OP(ropPSUBD, MMX_SUBD)
|
||||
MMX_OP(ropPSUBSB, MMX_SUBSB)
|
||||
MMX_OP(ropPSUBSW, MMX_SUBSW)
|
||||
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
|
||||
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
|
||||
|
||||
MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW);
|
||||
MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD);
|
||||
MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ);
|
||||
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
|
||||
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
|
||||
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
|
||||
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
|
||||
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
|
||||
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
|
||||
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
|
||||
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
|
||||
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
|
||||
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
|
||||
MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW);
|
||||
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
|
||||
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
|
||||
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
|
||||
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
|
||||
|
||||
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
|
||||
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
|
||||
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
|
||||
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
|
||||
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
|
||||
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
|
||||
|
||||
MMX_OP(ropPSRLW, MMX_PSRLW)
|
||||
MMX_OP(ropPSRLD, MMX_PSRLD)
|
||||
MMX_OP(ropPSRLQ, MMX_PSRLQ)
|
||||
MMX_OP(ropPSRAW, MMX_PSRAW)
|
||||
MMX_OP(ropPSRAD, MMX_PSRAD)
|
||||
MMX_OP(ropPSLLW, MMX_PSLLW)
|
||||
MMX_OP(ropPSLLD, MMX_PSLLD)
|
||||
MMX_OP(ropPSLLQ, MMX_PSLLQ)
|
||||
MMX_OP(ropPSRLW, MMX_PSRLW)
|
||||
MMX_OP(ropPSRLD, MMX_PSRLD)
|
||||
MMX_OP(ropPSRLQ, MMX_PSRLQ)
|
||||
MMX_OP(ropPSRAW, MMX_PSRAW)
|
||||
MMX_OP(ropPSRAD, MMX_PSRAD)
|
||||
MMX_OP(ropPSLLW, MMX_PSLLW)
|
||||
MMX_OP(ropPSLLD, MMX_PSLLD)
|
||||
MMX_OP(ropPSLLQ, MMX_PSLLQ)
|
||||
|
||||
MMX_OP(ropPMULLW, MMX_PMULLW);
|
||||
MMX_OP(ropPMULHW, MMX_PMULHW);
|
||||
MMX_OP(ropPMADDWD, MMX_PMADDWD);
|
||||
MMX_OP(ropPMULLW, MMX_PMULLW);
|
||||
MMX_OP(ropPMULHW, MMX_PMULHW);
|
||||
MMX_OP(ropPMADDWD, MMX_PMADDWD);
|
||||
|
||||
static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x10: /*PSRLW*/
|
||||
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAW*/
|
||||
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLW*/
|
||||
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x10: /*PSRLD*/
|
||||
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAD*/
|
||||
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLD*/
|
||||
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38)
|
||||
{
|
||||
case 0x10: /*PSRLQ*/
|
||||
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAQ*/
|
||||
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLQ*/
|
||||
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
codegen_mmx_entered = 0;
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x10: /*PSRLW*/
|
||||
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAW*/
|
||||
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLW*/
|
||||
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t
|
||||
ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x10: /*PSRLD*/
|
||||
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAD*/
|
||||
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLD*/
|
||||
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t
|
||||
ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int xmm_dst;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
|
||||
return 0;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
|
||||
switch (fetchdat & 0x38) {
|
||||
case 0x10: /*PSRLQ*/
|
||||
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20: /*PSRAQ*/
|
||||
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
case 0x30: /*PSLLQ*/
|
||||
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
|
||||
break;
|
||||
}
|
||||
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
codegen_mmx_entered = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,125 +1,129 @@
|
||||
#define SHIFT(size, size2, res_store, immediate) \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
{ \
|
||||
reg = LOAD_REG_ ## size(fetchdat & 7); \
|
||||
if (immediate) count = (fetchdat >> 8) & 0x1f; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
SAVE_EA(); \
|
||||
MEM_CHECK_WRITE_ ## size(target_seg); \
|
||||
reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \
|
||||
if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \
|
||||
} \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \
|
||||
\
|
||||
res_store((uintptr_t)&cpu_state.flags_op1, reg); \
|
||||
\
|
||||
switch (fetchdat & 0x38) \
|
||||
{ \
|
||||
case 0x20: case 0x30: /*SHL*/ \
|
||||
SHL_ ## size ## _IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \
|
||||
break; \
|
||||
\
|
||||
case 0x28: /*SHR*/ \
|
||||
SHR_ ## size ## _IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \
|
||||
break; \
|
||||
\
|
||||
case 0x38: /*SAR*/ \
|
||||
SAR_ ## size ## _IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
res_store((uintptr_t)&cpu_state.flags_res, reg); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
STORE_REG_ ## size ## _RELEASE(reg); \
|
||||
else \
|
||||
{ \
|
||||
LOAD_EA(); \
|
||||
MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \
|
||||
}
|
||||
#define SHIFT(size, size2, res_store, immediate) \
|
||||
if ((fetchdat & 0xc0) == 0xc0) { \
|
||||
reg = LOAD_REG_##size(fetchdat & 7); \
|
||||
if (immediate) \
|
||||
count = (fetchdat >> 8) & 0x1f; \
|
||||
} else { \
|
||||
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
SAVE_EA(); \
|
||||
MEM_CHECK_WRITE_##size(target_seg); \
|
||||
reg = MEM_LOAD_ADDR_EA_##size##_NO_ABRT(target_seg); \
|
||||
if (immediate) \
|
||||
count = fastreadb(cs + op_pc + 1) & 0x1f; \
|
||||
} \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op2, count); \
|
||||
\
|
||||
res_store((uintptr_t) &cpu_state.flags_op1, reg); \
|
||||
\
|
||||
switch (fetchdat & 0x38) { \
|
||||
case 0x20: \
|
||||
case 0x30: /*SHL*/ \
|
||||
SHL_##size##_IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHL##size2); \
|
||||
break; \
|
||||
\
|
||||
case 0x28: /*SHR*/ \
|
||||
SHR_##size##_IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SHR##size2); \
|
||||
break; \
|
||||
\
|
||||
case 0x38: /*SAR*/ \
|
||||
SAR_##size##_IMM(reg, count); \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.flags_op, FLAGS_SAR##size2); \
|
||||
break; \
|
||||
} \
|
||||
\
|
||||
res_store((uintptr_t) &cpu_state.flags_res, reg); \
|
||||
if ((fetchdat & 0xc0) == 0xc0) \
|
||||
STORE_REG_##size##_RELEASE(reg); \
|
||||
else { \
|
||||
LOAD_EA(); \
|
||||
MEM_STORE_ADDR_EA_##size##_NO_ABRT(target_seg, reg); \
|
||||
}
|
||||
|
||||
static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
|
||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
|
||||
|
||||
return op_pc + 2;
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
|
||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
|
||||
|
||||
return op_pc + 2;
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
|
||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
|
||||
|
||||
return op_pc + 2;
|
||||
return op_pc + 2;
|
||||
}
|
||||
|
||||
static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
|
||||
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
|
||||
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
x86seg *target_seg = NULL;
|
||||
int count = 1;
|
||||
int reg;
|
||||
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
if ((fetchdat & 0x38) < 0x20)
|
||||
return 0;
|
||||
|
||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
|
||||
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
@@ -1,238 +1,254 @@
|
||||
static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_W(opcode & 7);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_W(opcode & 7);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_L(opcode & 7);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_L(opcode & 7);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t imm = fetchdat & 0xffff;
|
||||
int host_reg;
|
||||
uint16_t imm = fetchdat & 0xffff;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
|
||||
return op_pc+2;
|
||||
return op_pc + 2;
|
||||
}
|
||||
static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t imm = fastreadl(cs + op_pc);
|
||||
int host_reg;
|
||||
uint32_t imm = fastreadl(cs + op_pc);
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
|
||||
return op_pc+4;
|
||||
return op_pc + 4;
|
||||
}
|
||||
|
||||
static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t imm = fetchdat & 0xff;
|
||||
int host_reg;
|
||||
uint16_t imm = fetchdat & 0xff;
|
||||
int host_reg;
|
||||
|
||||
if (imm & 0x80)
|
||||
imm |= 0xff00;
|
||||
if (imm & 0x80)
|
||||
imm |= 0xff00;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
|
||||
return op_pc+1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t imm = fetchdat & 0xff;
|
||||
int host_reg;
|
||||
uint32_t imm = fetchdat & 0xff;
|
||||
int host_reg;
|
||||
|
||||
if (imm & 0x80)
|
||||
imm |= 0xffffff00;
|
||||
if (imm & 0x80)
|
||||
imm |= 0xffffff00;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(imm);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
|
||||
return op_pc+1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
SP_MODIFY(2);
|
||||
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
SP_MODIFY(2);
|
||||
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
SP_MODIFY(4);
|
||||
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
SP_MODIFY(4);
|
||||
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
||||
SP_MODIFY(2);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
|
||||
SP_MODIFY(2);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
||||
SP_MODIFY(4);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
|
||||
SP_MODIFY(4);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
||||
SP_MODIFY(2+offset);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
|
||||
SP_MODIFY(2 + offset);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
|
||||
SP_MODIFY(4+offset);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &cpu_state.pc, 0);
|
||||
SP_MODIFY(4 + offset);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
int host_reg;
|
||||
uint16_t offset = fetchdat & 0xffff;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(op_pc+2);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-2);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 2);
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-2);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, (op_pc + 2 + offset) & 0xffff);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
static uint32_t ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropCALL_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
uint32_t offset = fastreadl(cs + op_pc);
|
||||
int host_reg;
|
||||
uint32_t offset = fastreadl(cs + op_pc);
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(op_pc+4);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_STACK_TO_EA(-4);
|
||||
host_reg = LOAD_REG_IMM(op_pc + 4);
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg);
|
||||
SP_MODIFY(-4);
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.pc, op_pc + 4 + offset);
|
||||
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_EBP_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
|
||||
ADD_HOST_REG_IMM_W(host_reg, 2);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
|
||||
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_EBP_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss);
|
||||
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
|
||||
ADD_HOST_REG_IMM_W(host_reg, 2);
|
||||
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
|
||||
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int host_reg;
|
||||
int host_reg;
|
||||
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
|
||||
LOAD_EBP_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
|
||||
ADD_HOST_REG_IMM(host_reg, 4);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
|
||||
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc);
|
||||
LOAD_EBP_TO_EA(0);
|
||||
MEM_LOAD_ADDR_EA_L(&cpu_state.seg_ss);
|
||||
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
|
||||
ADD_HOST_REG_IMM(host_reg, 4);
|
||||
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
|
||||
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
|
||||
|
||||
return op_pc;
|
||||
return op_pc;
|
||||
}
|
||||
|
||||
#define ROP_PUSH_SEG(seg) \
|
||||
static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int host_reg; \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(-2); \
|
||||
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \
|
||||
SP_MODIFY(-2); \
|
||||
\
|
||||
return op_pc; \
|
||||
} \
|
||||
static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int host_reg; \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(-4); \
|
||||
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \
|
||||
SP_MODIFY(-4); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
#define ROP_PUSH_SEG(seg) \
|
||||
static uint32_t ropPUSH_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int host_reg; \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(-2); \
|
||||
host_reg = LOAD_VAR_W((uintptr_t) &seg); \
|
||||
MEM_STORE_ADDR_EA_W(&cpu_state.seg_ss, host_reg); \
|
||||
SP_MODIFY(-2); \
|
||||
\
|
||||
return op_pc; \
|
||||
} \
|
||||
static uint32_t ropPUSH_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int host_reg; \
|
||||
\
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(-4); \
|
||||
host_reg = LOAD_VAR_W((uintptr_t) &seg); \
|
||||
MEM_STORE_ADDR_EA_L(&cpu_state.seg_ss, host_reg); \
|
||||
SP_MODIFY(-4); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
ROP_PUSH_SEG(CS)
|
||||
ROP_PUSH_SEG(DS)
|
||||
@@ -241,27 +257,27 @@ ROP_PUSH_SEG(FS)
|
||||
ROP_PUSH_SEG(GS)
|
||||
ROP_PUSH_SEG(SS)
|
||||
|
||||
#define ROP_POP_SEG(seg, rseg) \
|
||||
static uint32_t ropPOP_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(0); \
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
|
||||
LOAD_SEG(0, &rseg); \
|
||||
SP_MODIFY(2); \
|
||||
\
|
||||
return op_pc; \
|
||||
} \
|
||||
static uint32_t ropPOP_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(0); \
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
|
||||
LOAD_SEG(0, &rseg); \
|
||||
SP_MODIFY(4); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
#define ROP_POP_SEG(seg, rseg) \
|
||||
static uint32_t ropPOP_##seg##_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(0); \
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
|
||||
LOAD_SEG(0, &rseg); \
|
||||
SP_MODIFY(2); \
|
||||
\
|
||||
return op_pc; \
|
||||
} \
|
||||
static uint32_t ropPOP_##seg##_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
STORE_IMM_ADDR_L((uintptr_t) &cpu_state.oldpc, op_old_pc); \
|
||||
LOAD_STACK_TO_EA(0); \
|
||||
MEM_LOAD_ADDR_EA_W(&cpu_state.seg_ss); \
|
||||
LOAD_SEG(0, &rseg); \
|
||||
SP_MODIFY(4); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
ROP_POP_SEG(DS, cpu_state.seg_ds)
|
||||
ROP_POP_SEG(ES, cpu_state.seg_es)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
#define OP_XCHG_AX_(reg) \
|
||||
static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int ax_reg, host_reg, temp_reg; \
|
||||
\
|
||||
ax_reg = LOAD_REG_W(REG_AX); \
|
||||
host_reg = LOAD_REG_W(REG_ ## reg); \
|
||||
temp_reg = COPY_REG(host_reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
#define OP_XCHG_AX_(reg) \
|
||||
static uint32_t ropXCHG_AX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int ax_reg, host_reg, temp_reg; \
|
||||
\
|
||||
ax_reg = LOAD_REG_W(REG_AX); \
|
||||
host_reg = LOAD_REG_W(REG_##reg); \
|
||||
temp_reg = COPY_REG(host_reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_##reg); \
|
||||
STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
OP_XCHG_AX_(BX)
|
||||
OP_XCHG_AX_(CX)
|
||||
@@ -20,19 +20,19 @@ OP_XCHG_AX_(DI)
|
||||
OP_XCHG_AX_(SP)
|
||||
OP_XCHG_AX_(BP)
|
||||
|
||||
#define OP_XCHG_EAX_(reg) \
|
||||
static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int eax_reg, host_reg, temp_reg; \
|
||||
\
|
||||
eax_reg = LOAD_REG_L(REG_EAX); \
|
||||
host_reg = LOAD_REG_L(REG_ ## reg); \
|
||||
temp_reg = COPY_REG(host_reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
#define OP_XCHG_EAX_(reg) \
|
||||
static uint32_t ropXCHG_EAX_##reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
|
||||
{ \
|
||||
int eax_reg, host_reg, temp_reg; \
|
||||
\
|
||||
eax_reg = LOAD_REG_L(REG_EAX); \
|
||||
host_reg = LOAD_REG_L(REG_##reg); \
|
||||
temp_reg = COPY_REG(host_reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_##reg); \
|
||||
STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \
|
||||
\
|
||||
return op_pc; \
|
||||
}
|
||||
|
||||
OP_XCHG_EAX_(EBX)
|
||||
OP_XCHG_EAX_(ECX)
|
||||
@@ -42,48 +42,51 @@ OP_XCHG_EAX_(EDI)
|
||||
OP_XCHG_EAX_(ESP)
|
||||
OP_XCHG_EAX_(EBP)
|
||||
|
||||
static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_B(fetchdat & 7);
|
||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7);
|
||||
dst_reg = LOAD_REG_B(fetchdat & 7);
|
||||
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_W(fetchdat & 7);
|
||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7);
|
||||
dst_reg = LOAD_REG_W(fetchdat & 7);
|
||||
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
static uint32_t
|
||||
ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
|
||||
{
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
int src_reg, dst_reg, temp_reg;
|
||||
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
if ((fetchdat & 0xc0) != 0xc0)
|
||||
return 0;
|
||||
|
||||
dst_reg = LOAD_REG_L(fetchdat & 7);
|
||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7);
|
||||
dst_reg = LOAD_REG_L(fetchdat & 7);
|
||||
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
|
||||
temp_reg = COPY_REG(src_reg);
|
||||
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
|
||||
STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7);
|
||||
|
||||
return op_pc + 1;
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,23 @@
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
#define HASH(l) ((l) &0x1ffff)
|
||||
|
||||
#define BLOCK_EXIT_OFFSET 0x7e0
|
||||
#ifdef OLD_GPF
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
#else
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12)
|
||||
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 12)
|
||||
#endif
|
||||
|
||||
#define BLOCK_MAX 1620
|
||||
|
||||
enum
|
||||
{
|
||||
OP_RET = 0xc3
|
||||
enum {
|
||||
OP_RET = 0xc3
|
||||
};
|
||||
|
||||
#define NR_HOST_REGS 4
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,24 +1,23 @@
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
#define HASH(l) ((l) &0x1ffff)
|
||||
|
||||
#define BLOCK_EXIT_OFFSET 0x7f0
|
||||
#ifdef OLD_GPF
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
#else
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14)
|
||||
# define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 14)
|
||||
#endif
|
||||
|
||||
#define BLOCK_MAX 1720
|
||||
|
||||
enum
|
||||
{
|
||||
OP_RET = 0xc3
|
||||
enum {
|
||||
OP_RET = 0xc3
|
||||
};
|
||||
|
||||
#define NR_HOST_REGS 4
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake build script.
|
||||
# CMake build script.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
# Copyright 2020,2021 David Hrdlička.
|
||||
#
|
||||
|
||||
if(DYNAREC)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,34 +30,33 @@
|
||||
same page).
|
||||
*/
|
||||
|
||||
typedef struct codeblock_t
|
||||
{
|
||||
uint32_t pc;
|
||||
uint32_t _cs;
|
||||
uint32_t phys, phys_2;
|
||||
uint16_t status;
|
||||
uint16_t flags;
|
||||
uint8_t ins;
|
||||
uint8_t TOP;
|
||||
typedef struct codeblock_t {
|
||||
uint32_t pc;
|
||||
uint32_t _cs;
|
||||
uint32_t phys, phys_2;
|
||||
uint16_t status;
|
||||
uint16_t flags;
|
||||
uint8_t ins;
|
||||
uint8_t TOP;
|
||||
|
||||
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
||||
fails.*/
|
||||
uint16_t parent, left, right;
|
||||
/*Pointers for codeblock tree, used to search for blocks when hash lookup
|
||||
fails.*/
|
||||
uint16_t parent, left, right;
|
||||
|
||||
uint8_t *data;
|
||||
uint8_t *data;
|
||||
|
||||
uint64_t page_mask, page_mask2;
|
||||
uint64_t *dirty_mask, *dirty_mask2;
|
||||
uint64_t page_mask, page_mask2;
|
||||
uint64_t *dirty_mask, *dirty_mask2;
|
||||
|
||||
/*Previous and next pointers, for the codeblock list associated with
|
||||
each physical page. Two sets of pointers, as a codeblock can be
|
||||
present in two pages.*/
|
||||
uint16_t prev, next;
|
||||
uint16_t prev_2, next_2;
|
||||
/*Previous and next pointers, for the codeblock list associated with
|
||||
each physical page. Two sets of pointers, as a codeblock can be
|
||||
present in two pages.*/
|
||||
uint16_t prev, next;
|
||||
uint16_t prev_2, next_2;
|
||||
|
||||
/*First mem_block_t used by this block. Any subsequent mem_block_ts
|
||||
will be in the list starting at head_mem_block->next.*/
|
||||
struct mem_block_t *head_mem_block;
|
||||
/*First mem_block_t used by this block. Any subsequent mem_block_ts
|
||||
will be in the list starting at head_mem_block->next.*/
|
||||
struct mem_block_t *head_mem_block;
|
||||
} codeblock_t;
|
||||
|
||||
extern codeblock_t *codeblock;
|
||||
@@ -83,262 +82,233 @@ extern uint8_t *block_write_data;
|
||||
/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
|
||||
#define CODEBLOCK_NO_IMMEDIATES 0x80
|
||||
|
||||
#define BLOCK_PC_INVALID 0xffffffff
|
||||
#define BLOCK_PC_INVALID 0xffffffff
|
||||
|
||||
#define BLOCK_INVALID 0
|
||||
#define BLOCK_INVALID 0
|
||||
|
||||
static inline int get_block_nr(codeblock_t *block)
|
||||
static inline int
|
||||
get_block_nr(codeblock_t *block)
|
||||
{
|
||||
return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
|
||||
return ((uintptr_t) block - (uintptr_t) codeblock) / sizeof(codeblock_t);
|
||||
}
|
||||
|
||||
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||
static inline codeblock_t *
|
||||
codeblock_tree_find(uint32_t phys, uint32_t _cs)
|
||||
{
|
||||
codeblock_t *block;
|
||||
uint64_t a = _cs | ((uint64_t)phys << 32);
|
||||
codeblock_t *block;
|
||||
uint64_t a = _cs | ((uint64_t) phys << 32);
|
||||
|
||||
if (!pages[phys >> 12].head)
|
||||
return NULL;
|
||||
if (!pages[phys >> 12].head)
|
||||
return NULL;
|
||||
|
||||
block = &codeblock[pages[phys >> 12].head];
|
||||
while (block)
|
||||
{
|
||||
uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32);
|
||||
if (a == block_cmp)
|
||||
{
|
||||
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
|
||||
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||
break;
|
||||
}
|
||||
if (a < block_cmp)
|
||||
block = block->left ? &codeblock[block->left] : NULL;
|
||||
else
|
||||
block = block->right ? &codeblock[block->right] : NULL;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
static inline void codeblock_tree_add(codeblock_t *new_block)
|
||||
{
|
||||
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
|
||||
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
|
||||
|
||||
if (!pages[new_block->phys >> 12].head)
|
||||
{
|
||||
pages[new_block->phys >> 12].head = get_block_nr(new_block);
|
||||
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
|
||||
block = &codeblock[pages[phys >> 12].head];
|
||||
while (block) {
|
||||
uint64_t block_cmp = block->_cs | ((uint64_t) block->phys << 32);
|
||||
if (a == block_cmp) {
|
||||
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
|
||||
break;
|
||||
}
|
||||
if (a < block_cmp)
|
||||
block = block->left ? &codeblock[block->left] : NULL;
|
||||
else
|
||||
{
|
||||
codeblock_t *old_block = NULL;
|
||||
uint64_t old_block_cmp = 0;
|
||||
block = block->right ? &codeblock[block->right] : NULL;
|
||||
}
|
||||
|
||||
while (block)
|
||||
{
|
||||
old_block = block;
|
||||
old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32);
|
||||
|
||||
if (a < old_block_cmp)
|
||||
block = block->left ? &codeblock[block->left] : NULL;
|
||||
else
|
||||
block = block->right ? &codeblock[block->right] : NULL;
|
||||
}
|
||||
|
||||
if (a < old_block_cmp)
|
||||
old_block->left = get_block_nr(new_block);
|
||||
else
|
||||
old_block->right = get_block_nr(new_block);
|
||||
|
||||
new_block->parent = get_block_nr(old_block);
|
||||
new_block->left = new_block->right = BLOCK_INVALID;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
static inline void codeblock_tree_delete(codeblock_t *block)
|
||||
static inline void
|
||||
codeblock_tree_add(codeblock_t *new_block)
|
||||
{
|
||||
uint16_t parent_nr = block->parent;
|
||||
codeblock_t *parent;
|
||||
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
|
||||
uint64_t a = new_block->_cs | ((uint64_t) new_block->phys << 32);
|
||||
|
||||
if (block->parent)
|
||||
parent = &codeblock[block->parent];
|
||||
if (!pages[new_block->phys >> 12].head) {
|
||||
pages[new_block->phys >> 12].head = get_block_nr(new_block);
|
||||
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
|
||||
} else {
|
||||
codeblock_t *old_block = NULL;
|
||||
uint64_t old_block_cmp = 0;
|
||||
|
||||
while (block) {
|
||||
old_block = block;
|
||||
old_block_cmp = old_block->_cs | ((uint64_t) old_block->phys << 32);
|
||||
|
||||
if (a < old_block_cmp)
|
||||
block = block->left ? &codeblock[block->left] : NULL;
|
||||
else
|
||||
block = block->right ? &codeblock[block->right] : NULL;
|
||||
}
|
||||
|
||||
if (a < old_block_cmp)
|
||||
old_block->left = get_block_nr(new_block);
|
||||
else
|
||||
parent = NULL;
|
||||
old_block->right = get_block_nr(new_block);
|
||||
|
||||
if (!block->left && !block->right)
|
||||
{
|
||||
/*Easy case - remove from parent*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = BLOCK_INVALID;
|
||||
else
|
||||
{
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
parent->left = BLOCK_INVALID;
|
||||
if (parent->right == block_nr)
|
||||
parent->right = BLOCK_INVALID;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!block->left)
|
||||
{
|
||||
/*Only right node*/
|
||||
if (!parent_nr)
|
||||
{
|
||||
pages[block->phys >> 12].head = block->right;
|
||||
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
{
|
||||
parent->left = block->right;
|
||||
codeblock[parent->left].parent = parent_nr;
|
||||
}
|
||||
if (parent->right == block_nr)
|
||||
{
|
||||
parent->right = block->right;
|
||||
codeblock[parent->right].parent = parent_nr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (!block->right)
|
||||
{
|
||||
/*Only left node*/
|
||||
if (!parent_nr)
|
||||
{
|
||||
pages[block->phys >> 12].head = block->left;
|
||||
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
{
|
||||
parent->left = block->left;
|
||||
codeblock[parent->left].parent = parent_nr;
|
||||
}
|
||||
if (parent->right == block_nr)
|
||||
{
|
||||
parent->right = block->left;
|
||||
codeblock[parent->right].parent = parent_nr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
||||
codeblock_t *lowest = &codeblock[block->right], *highest;
|
||||
codeblock_t *old_parent;
|
||||
uint16_t lowest_nr;
|
||||
|
||||
while (lowest->left)
|
||||
lowest = &codeblock[lowest->left];
|
||||
lowest_nr = get_block_nr(lowest);
|
||||
|
||||
old_parent = &codeblock[lowest->parent];
|
||||
|
||||
/*Replace deleted node with lowest node*/
|
||||
if (!parent_nr)
|
||||
pages[block->phys >> 12].head = lowest_nr;
|
||||
else
|
||||
{
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
parent->left = lowest_nr;
|
||||
if (parent->right == block_nr)
|
||||
parent->right = lowest_nr;
|
||||
}
|
||||
|
||||
lowest->parent = parent_nr;
|
||||
lowest->left = block->left;
|
||||
if (lowest->left)
|
||||
codeblock[lowest->left].parent = lowest_nr;
|
||||
|
||||
old_parent->left = BLOCK_INVALID;
|
||||
|
||||
highest = &codeblock[lowest->right];
|
||||
if (!lowest->right)
|
||||
{
|
||||
if (lowest_nr != block->right)
|
||||
{
|
||||
lowest->right = block->right;
|
||||
codeblock[block->right].parent = lowest_nr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (highest->right)
|
||||
highest = &codeblock[highest->right];
|
||||
|
||||
if (block->right && block->right != lowest_nr)
|
||||
{
|
||||
highest->right = block->right;
|
||||
codeblock[block->right].parent = get_block_nr(highest);
|
||||
}
|
||||
}
|
||||
new_block->parent = get_block_nr(old_block);
|
||||
new_block->left = new_block->right = BLOCK_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
#define PAGE_MASK_MASK 63
|
||||
static inline void
|
||||
codeblock_tree_delete(codeblock_t *block)
|
||||
{
|
||||
uint16_t parent_nr = block->parent;
|
||||
codeblock_t *parent;
|
||||
|
||||
if (block->parent)
|
||||
parent = &codeblock[block->parent];
|
||||
else
|
||||
parent = NULL;
|
||||
|
||||
if (!block->left && !block->right) {
|
||||
/*Easy case - remove from parent*/
|
||||
if (!parent)
|
||||
pages[block->phys >> 12].head = BLOCK_INVALID;
|
||||
else {
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
parent->left = BLOCK_INVALID;
|
||||
if (parent->right == block_nr)
|
||||
parent->right = BLOCK_INVALID;
|
||||
}
|
||||
return;
|
||||
} else if (!block->left) {
|
||||
/*Only right node*/
|
||||
if (!parent_nr) {
|
||||
pages[block->phys >> 12].head = block->right;
|
||||
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||
} else {
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr) {
|
||||
parent->left = block->right;
|
||||
codeblock[parent->left].parent = parent_nr;
|
||||
}
|
||||
if (parent->right == block_nr) {
|
||||
parent->right = block->right;
|
||||
codeblock[parent->right].parent = parent_nr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else if (!block->right) {
|
||||
/*Only left node*/
|
||||
if (!parent_nr) {
|
||||
pages[block->phys >> 12].head = block->left;
|
||||
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
|
||||
} else {
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr) {
|
||||
parent->left = block->left;
|
||||
codeblock[parent->left].parent = parent_nr;
|
||||
}
|
||||
if (parent->right == block_nr) {
|
||||
parent->right = block->left;
|
||||
codeblock[parent->right].parent = parent_nr;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
/*Difficult case - node has two children. Walk right child to find lowest node*/
|
||||
codeblock_t *lowest = &codeblock[block->right], *highest;
|
||||
codeblock_t *old_parent;
|
||||
uint16_t lowest_nr;
|
||||
|
||||
while (lowest->left)
|
||||
lowest = &codeblock[lowest->left];
|
||||
lowest_nr = get_block_nr(lowest);
|
||||
|
||||
old_parent = &codeblock[lowest->parent];
|
||||
|
||||
/*Replace deleted node with lowest node*/
|
||||
if (!parent_nr)
|
||||
pages[block->phys >> 12].head = lowest_nr;
|
||||
else {
|
||||
uint16_t block_nr = get_block_nr(block);
|
||||
|
||||
if (parent->left == block_nr)
|
||||
parent->left = lowest_nr;
|
||||
if (parent->right == block_nr)
|
||||
parent->right = lowest_nr;
|
||||
}
|
||||
|
||||
lowest->parent = parent_nr;
|
||||
lowest->left = block->left;
|
||||
if (lowest->left)
|
||||
codeblock[lowest->left].parent = lowest_nr;
|
||||
|
||||
old_parent->left = BLOCK_INVALID;
|
||||
|
||||
highest = &codeblock[lowest->right];
|
||||
if (!lowest->right) {
|
||||
if (lowest_nr != block->right) {
|
||||
lowest->right = block->right;
|
||||
codeblock[block->right].parent = lowest_nr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
while (highest->right)
|
||||
highest = &codeblock[highest->right];
|
||||
|
||||
if (block->right && block->right != lowest_nr) {
|
||||
highest->right = block->right;
|
||||
codeblock[block->right].parent = get_block_nr(highest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PAGE_MASK_MASK 63
|
||||
#define PAGE_MASK_SHIFT 6
|
||||
|
||||
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
|
||||
|
||||
static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
|
||||
static inline void
|
||||
codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
|
||||
{
|
||||
if (len == 1)
|
||||
{
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK)
|
||||
{
|
||||
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
}
|
||||
if (len == 1) {
|
||||
if (block->flags & CODEBLOCK_BYTE_MASK) {
|
||||
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t) 1 << (start_pc & PAGE_MASK_MASK));
|
||||
} else {
|
||||
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
|
||||
block->page_mask |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
else
|
||||
block->page_mask2 |= ((uint64_t) 1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
|
||||
}
|
||||
else
|
||||
codegen_mark_code_present_multibyte(block, start_pc, len);
|
||||
} else
|
||||
codegen_mark_code_present_multibyte(block, start_pc, len);
|
||||
}
|
||||
|
||||
void codegen_init();
|
||||
void codegen_close();
|
||||
void codegen_reset();
|
||||
void codegen_block_init(uint32_t phys_addr);
|
||||
void codegen_block_remove();
|
||||
void codegen_block_start_recompile(codeblock_t *block);
|
||||
void codegen_block_end_recompile(codeblock_t *block);
|
||||
void codegen_block_end();
|
||||
void codegen_delete_block(codeblock_t *block);
|
||||
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
||||
void codegen_generate_seg_restore();
|
||||
void codegen_set_op32();
|
||||
void codegen_flush();
|
||||
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||
extern void codegen_init(void);
|
||||
extern void codegen_close(void);
|
||||
extern void codegen_reset(void);
|
||||
extern void codegen_block_init(uint32_t phys_addr);
|
||||
extern void codegen_block_remove(void);
|
||||
extern void codegen_block_start_recompile(codeblock_t *block);
|
||||
extern void codegen_block_end_recompile(codeblock_t *block);
|
||||
extern void codegen_block_end(void);
|
||||
extern void codegen_delete_block(codeblock_t *block);
|
||||
extern void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
|
||||
extern void codegen_generate_seg_restore(void);
|
||||
extern void codegen_set_op32(void);
|
||||
extern void codegen_flush(void);
|
||||
extern void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||
struct ir_data_t;
|
||||
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
|
||||
void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
|
||||
extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
|
||||
int codegen_purge_purgable_list();
|
||||
extern int codegen_purge_purgable_list(void);
|
||||
/*Delete a random code block to free memory. This is obviously quite expensive, and
|
||||
will only be called when the allocator is out of memory*/
|
||||
void codegen_delete_random_block(int required_mem_block);
|
||||
extern void codegen_delete_random_block(int required_mem_block);
|
||||
|
||||
extern int cpu_block_end;
|
||||
extern int cpu_block_end;
|
||||
extern uint32_t codegen_endpc;
|
||||
|
||||
extern int cpu_reps;
|
||||
@@ -346,21 +316,20 @@ extern int cpu_notreps;
|
||||
|
||||
extern int codegen_block_cycles;
|
||||
|
||||
extern void (*codegen_timing_start)();
|
||||
extern void (*codegen_timing_start)(void);
|
||||
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
extern void (*codegen_timing_block_start)();
|
||||
extern void (*codegen_timing_block_end)();
|
||||
extern int (*codegen_timing_jump_cycles)();
|
||||
extern void (*codegen_timing_block_start)(void);
|
||||
extern void (*codegen_timing_block_end)(void);
|
||||
extern int (*codegen_timing_jump_cycles)(void);
|
||||
|
||||
typedef struct codegen_timing_t
|
||||
{
|
||||
void (*start)();
|
||||
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
void (*block_start)();
|
||||
void (*block_end)();
|
||||
int (*jump_cycles)();
|
||||
typedef struct codegen_timing_t {
|
||||
void (*start)(void);
|
||||
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
|
||||
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
|
||||
void (*block_start)(void);
|
||||
void (*block_end)(void);
|
||||
int (*jump_cycles)(void);
|
||||
} codegen_timing_t;
|
||||
|
||||
extern codegen_timing_t codegen_timing_pentium;
|
||||
@@ -371,7 +340,6 @@ extern codegen_timing_t codegen_timing_winchip2;
|
||||
extern codegen_timing_t codegen_timing_k6;
|
||||
extern codegen_timing_t codegen_timing_p6;
|
||||
|
||||
|
||||
void codegen_timing_set(codegen_timing_t *timing);
|
||||
|
||||
extern int block_current;
|
||||
@@ -382,8 +350,8 @@ extern int block_pos;
|
||||
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
|
||||
extern uint32_t recomp_page;
|
||||
|
||||
extern x86seg *op_ea_seg;
|
||||
extern int op_ssegs;
|
||||
extern x86seg *op_ea_seg;
|
||||
extern int op_ssegs;
|
||||
extern uint32_t op_old_pc;
|
||||
|
||||
/*Set to 1 if flags have been changed in the block being recompiled, and hence
|
||||
@@ -398,13 +366,13 @@ extern int codegen_reg_loaded[8];
|
||||
|
||||
extern int codegen_in_recompile;
|
||||
|
||||
void codegen_generate_reset();
|
||||
void codegen_generate_reset(void);
|
||||
|
||||
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
|
||||
int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
|
||||
void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction);
|
||||
|
||||
#ifdef DEBUG_EXTRA
|
||||
extern uint32_t instr_counts[256*256];
|
||||
extern uint32_t instr_counts[256 * 256];
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,34 +9,36 @@
|
||||
|
||||
static struct
|
||||
{
|
||||
int count;
|
||||
int dest_reg;
|
||||
} acc_regs[] =
|
||||
{
|
||||
[ACCREG_cycles] = {0, IREG_cycles}
|
||||
int count;
|
||||
int dest_reg;
|
||||
} acc_regs[] = {
|
||||
[ACCREG_cycles] = {0, IREG_cycles}
|
||||
};
|
||||
|
||||
void codegen_accumulate(ir_data_t *ir, int acc_reg, int delta)
|
||||
void
|
||||
codegen_accumulate(ir_data_t *ir, int acc_reg, int delta)
|
||||
{
|
||||
acc_regs[acc_reg].count += delta;
|
||||
acc_regs[acc_reg].count += delta;
|
||||
|
||||
#ifdef USE_ACYCS
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta);
|
||||
}
|
||||
if ((acc_reg == ACCREG_cycles) && (delta != 0)) {
|
||||
uop_ADD_IMM(ir, IREG_acycs, IREG_acycs, -delta);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void codegen_accumulate_flush(ir_data_t *ir)
|
||||
void
|
||||
codegen_accumulate_flush(ir_data_t *ir)
|
||||
{
|
||||
if (acc_regs[0].count) {
|
||||
uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count);
|
||||
}
|
||||
if (acc_regs[0].count) {
|
||||
uop_ADD_IMM(ir, acc_regs[0].dest_reg, acc_regs[0].dest_reg, acc_regs[0].count);
|
||||
}
|
||||
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
void codegen_accumulate_reset()
|
||||
void
|
||||
codegen_accumulate_reset(void)
|
||||
{
|
||||
acc_regs[0].count = 0;
|
||||
acc_regs[0].count = 0;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
enum
|
||||
{
|
||||
ACCREG_cycles = 0,
|
||||
enum {
|
||||
ACCREG_cycles = 0,
|
||||
|
||||
ACCREG_COUNT
|
||||
ACCREG_COUNT
|
||||
};
|
||||
|
||||
struct ir_data_t;
|
||||
|
||||
void codegen_accumulate(struct ir_data_t *ir, int acc_reg, int delta);
|
||||
void codegen_accumulate_flush(struct ir_data_t *ir);
|
||||
void codegen_accumulate_reset();
|
||||
void codegen_accumulate_reset(void);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
#include <windows.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -17,118 +17,116 @@
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
|
||||
typedef struct mem_block_t
|
||||
{
|
||||
uint32_t offset; /*Offset into mem_block_alloc*/
|
||||
uint32_t next;
|
||||
uint16_t code_block;
|
||||
typedef struct mem_block_t {
|
||||
uint32_t offset; /*Offset into mem_block_alloc*/
|
||||
uint32_t next;
|
||||
uint16_t code_block;
|
||||
} mem_block_t;
|
||||
|
||||
static mem_block_t mem_blocks[MEM_BLOCK_NR];
|
||||
static uint32_t mem_block_free_list;
|
||||
static uint8_t *mem_block_alloc = NULL;
|
||||
static uint32_t mem_block_free_list;
|
||||
static uint8_t *mem_block_alloc = NULL;
|
||||
|
||||
int codegen_allocator_usage = 0;
|
||||
|
||||
void codegen_allocator_init()
|
||||
void
|
||||
codegen_allocator_init(void)
|
||||
{
|
||||
int c;
|
||||
int c;
|
||||
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
/* TODO: check deployment target: older Intel-based versions of macOS don't play
|
||||
nice with MAP_JIT. */
|
||||
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
/* TODO: check deployment target: older Intel-based versions of macOS don't play
|
||||
nice with MAP_JIT. */
|
||||
#elif defined(__APPLE__) && defined(MAP_JIT)
|
||||
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE|MAP_JIT, -1, 0);
|
||||
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE | MAP_JIT, -1, 0);
|
||||
#else
|
||||
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, -1, 0);
|
||||
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
#endif
|
||||
|
||||
for (c = 0; c < MEM_BLOCK_NR; c++)
|
||||
{
|
||||
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
|
||||
mem_blocks[c].code_block = BLOCK_INVALID;
|
||||
if (c < MEM_BLOCK_NR-1)
|
||||
mem_blocks[c].next = c+2;
|
||||
else
|
||||
mem_blocks[c].next = 0;
|
||||
}
|
||||
mem_block_free_list = 1;
|
||||
}
|
||||
|
||||
mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block)
|
||||
{
|
||||
mem_block_t *block;
|
||||
uint32_t block_nr;
|
||||
|
||||
while (!mem_block_free_list)
|
||||
{
|
||||
/*Pick a random memory block and free the owning code block*/
|
||||
block_nr = rand() & MEM_BLOCK_MASK;
|
||||
block = &mem_blocks[block_nr];
|
||||
|
||||
if (block->code_block && block->code_block != code_block)
|
||||
codegen_delete_block(&codeblock[block->code_block]);
|
||||
}
|
||||
|
||||
/*Remove from free list*/
|
||||
block_nr = mem_block_free_list;
|
||||
block = &mem_blocks[block_nr-1];
|
||||
mem_block_free_list = block->next;
|
||||
|
||||
block->code_block = code_block;
|
||||
if (parent)
|
||||
{
|
||||
/*Add to parent list*/
|
||||
block->next = parent->next;
|
||||
parent->next = block_nr;
|
||||
}
|
||||
for (c = 0; c < MEM_BLOCK_NR; c++) {
|
||||
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
|
||||
mem_blocks[c].code_block = BLOCK_INVALID;
|
||||
if (c < MEM_BLOCK_NR - 1)
|
||||
mem_blocks[c].next = c + 2;
|
||||
else
|
||||
block->next = 0;
|
||||
|
||||
codegen_allocator_usage++;
|
||||
return block;
|
||||
mem_blocks[c].next = 0;
|
||||
}
|
||||
mem_block_free_list = 1;
|
||||
}
|
||||
void codegen_allocator_free(mem_block_t *block)
|
||||
|
||||
mem_block_t *
|
||||
codegen_allocator_allocate(mem_block_t *parent, int code_block)
|
||||
{
|
||||
int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1;
|
||||
mem_block_t *block;
|
||||
uint32_t block_nr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int next_block_nr = block->next;
|
||||
codegen_allocator_usage--;
|
||||
while (!mem_block_free_list) {
|
||||
/*Pick a random memory block and free the owning code block*/
|
||||
block_nr = rand() & MEM_BLOCK_MASK;
|
||||
block = &mem_blocks[block_nr];
|
||||
|
||||
block->next = mem_block_free_list;
|
||||
block->code_block = BLOCK_INVALID;
|
||||
mem_block_free_list = block_nr;
|
||||
block_nr = next_block_nr;
|
||||
if (block->code_block && block->code_block != code_block)
|
||||
codegen_delete_block(&codeblock[block->code_block]);
|
||||
}
|
||||
|
||||
if (block_nr)
|
||||
block = &mem_blocks[block_nr - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
/*Remove from free list*/
|
||||
block_nr = mem_block_free_list;
|
||||
block = &mem_blocks[block_nr - 1];
|
||||
mem_block_free_list = block->next;
|
||||
|
||||
block->code_block = code_block;
|
||||
if (parent) {
|
||||
/*Add to parent list*/
|
||||
block->next = parent->next;
|
||||
parent->next = block_nr;
|
||||
} else
|
||||
block->next = 0;
|
||||
|
||||
codegen_allocator_usage++;
|
||||
return block;
|
||||
}
|
||||
|
||||
uint8_t *codeblock_allocator_get_ptr(mem_block_t *block)
|
||||
void
|
||||
codegen_allocator_free(mem_block_t *block)
|
||||
{
|
||||
return &mem_block_alloc[block->offset];
|
||||
int block_nr = (((uintptr_t) block - (uintptr_t) mem_blocks) / sizeof(mem_block_t)) + 1;
|
||||
|
||||
while (1) {
|
||||
int next_block_nr = block->next;
|
||||
codegen_allocator_usage--;
|
||||
|
||||
block->next = mem_block_free_list;
|
||||
block->code_block = BLOCK_INVALID;
|
||||
mem_block_free_list = block_nr;
|
||||
block_nr = next_block_nr;
|
||||
|
||||
if (block_nr)
|
||||
block = &mem_blocks[block_nr - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_allocator_clean_blocks(struct mem_block_t *block)
|
||||
uint8_t *
|
||||
codeblock_allocator_get_ptr(mem_block_t *block)
|
||||
{
|
||||
return &mem_block_alloc[block->offset];
|
||||
}
|
||||
|
||||
void
|
||||
codegen_allocator_clean_blocks(struct mem_block_t *block)
|
||||
{
|
||||
#if defined __ARM_EABI__ || defined _ARM_ || defined __aarch64__ || defined _M_ARM || defined _M_ARM64
|
||||
while (1)
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
|
||||
#else
|
||||
FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE);
|
||||
#endif
|
||||
if (block->next)
|
||||
block = &mem_blocks[block->next - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
while (1) {
|
||||
# ifndef _MSC_VER
|
||||
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
|
||||
# else
|
||||
FlushInstructionCache(GetCurrentProcess(), &mem_block_alloc[block->offset], MEM_BLOCK_SIZE);
|
||||
# endif
|
||||
if (block->next)
|
||||
block = &mem_blocks[block->next - 1];
|
||||
else
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to
|
||||
+/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/
|
||||
#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
|
||||
#define MEM_BLOCK_NR 32768
|
||||
# define MEM_BLOCK_NR 32768
|
||||
#else
|
||||
#define MEM_BLOCK_NR 131072
|
||||
# define MEM_BLOCK_NR 131072
|
||||
#endif
|
||||
|
||||
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
|
||||
#define MEM_BLOCK_MASK (MEM_BLOCK_NR - 1)
|
||||
#define MEM_BLOCK_SIZE 0x3c0
|
||||
|
||||
void codegen_allocator_init();
|
||||
void codegen_allocator_init(void);
|
||||
/*Allocate a mem_block_t, and the associated backing memory.
|
||||
If parent is non-NULL, then the new block will be added to the list in
|
||||
parent->next*/
|
||||
|
||||
@@ -2,25 +2,25 @@
|
||||
#define _CODEGEN_BACKEND_H_
|
||||
|
||||
#if defined __amd64__ || defined _M_X64
|
||||
#include "codegen_backend_x86-64.h"
|
||||
# include "codegen_backend_x86-64.h"
|
||||
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined _M_IX86
|
||||
#include "codegen_backend_x86.h"
|
||||
# include "codegen_backend_x86.h"
|
||||
#elif defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
|
||||
#include "codegen_backend_arm.h"
|
||||
# include "codegen_backend_arm.h"
|
||||
#elif defined __aarch64__ || defined _M_ARM64
|
||||
#include "codegen_backend_arm64.h"
|
||||
# include "codegen_backend_arm64.h"
|
||||
#else
|
||||
#error Dynamic recompiler not implemented on your platform
|
||||
# error Dynamic recompiler not implemented on your platform
|
||||
#endif
|
||||
|
||||
void codegen_backend_init();
|
||||
void codegen_backend_init(void);
|
||||
void codegen_backend_prologue(codeblock_t *block);
|
||||
void codegen_backend_epilogue(codeblock_t *block);
|
||||
|
||||
struct ir_data_t;
|
||||
struct uop_t;
|
||||
|
||||
struct ir_data_t *codegen_get_ir_data();
|
||||
struct ir_data_t *codegen_get_ir_data(void);
|
||||
|
||||
typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
|
||||
|
||||
@@ -29,10 +29,9 @@ extern const uOpFn uop_handlers[];
|
||||
/*Register will not be preserved across function calls*/
|
||||
#define HOST_REG_FLAG_VOLATILE (1 << 0)
|
||||
|
||||
typedef struct host_reg_def_t
|
||||
{
|
||||
int reg;
|
||||
int flags;
|
||||
typedef struct host_reg_def_t {
|
||||
int reg;
|
||||
int flags;
|
||||
} host_reg_def_t;
|
||||
|
||||
extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS];
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#if defined __ARM_EABI__ || defined _ARM_ || defined _M_ARM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/mem.h>
|
||||
# include <stdint.h>
|
||||
# include <stdlib.h>
|
||||
# include <86box/86box.h>
|
||||
# include "cpu.h"
|
||||
# include <86box/mem.h>
|
||||
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
#include "codegen_reg.h"
|
||||
#include "x86.h"
|
||||
#include "x87.h"
|
||||
# include "codegen.h"
|
||||
# include "codegen_allocator.h"
|
||||
# include "codegen_backend.h"
|
||||
# include "codegen_backend_arm_defs.h"
|
||||
# include "codegen_backend_arm_ops.h"
|
||||
# include "codegen_reg.h"
|
||||
# include "x86.h"
|
||||
# include "x87.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
# if defined(__linux__) || defined(__APPLE__)
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
@@ -43,329 +43,325 @@ void *codegen_fp_round;
|
||||
void *codegen_gpf_rout;
|
||||
void *codegen_exit_rout;
|
||||
|
||||
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
{REG_R4, 0},
|
||||
{REG_R5, 0},
|
||||
{REG_R6, 0},
|
||||
{REG_R7, 0},
|
||||
{REG_R8, 0},
|
||||
{REG_R9, 0},
|
||||
{REG_R11, 0}
|
||||
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
|
||||
{REG_R4, 0},
|
||||
{ REG_R5, 0},
|
||||
{ REG_R6, 0},
|
||||
{ REG_R7, 0},
|
||||
{ REG_R8, 0},
|
||||
{ REG_R9, 0},
|
||||
{ REG_R11, 0}
|
||||
};
|
||||
|
||||
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||
{
|
||||
{REG_D8, 0},
|
||||
{REG_D9, 0},
|
||||
{REG_D10, 0},
|
||||
{REG_D11, 0},
|
||||
{REG_D12, 0},
|
||||
{REG_D13, 0},
|
||||
{REG_D14, 0},
|
||||
{REG_D15, 0}
|
||||
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
|
||||
{REG_D8, 0},
|
||||
{ REG_D9, 0},
|
||||
{ REG_D10, 0},
|
||||
{ REG_D11, 0},
|
||||
{ REG_D12, 0},
|
||||
{ REG_D13, 0},
|
||||
{ REG_D14, 0},
|
||||
{ REG_D15, 0}
|
||||
};
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||
static void
|
||||
build_load_routine(codeblock_t *block, int size, int is_float)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R1, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 4 && is_float)
|
||||
{
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
else if (size == 8)
|
||||
{
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R2, (uint32_t) readlookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
|
||||
if (size != 1) {
|
||||
host_arm_TST_IMM(block, REG_R0, size - 1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R1, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 4 && is_float) {
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||
} else if (size == 8) {
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
|
||||
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t)readmembl);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t)readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t)readmemll);
|
||||
else if (size == 8)
|
||||
host_arm_BL(block, (uintptr_t)readmemql);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
if (size == 4 && is_float)
|
||||
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
|
||||
else if (size == 8)
|
||||
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||
*branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t) readmembl);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t) readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t) readmemll);
|
||||
else if (size == 8)
|
||||
host_arm_BL(block, (uintptr_t) readmemql);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
if (size == 4 && is_float)
|
||||
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
|
||||
else if (size == 8)
|
||||
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||
static void
|
||||
build_store_routine(codeblock_t *block, int size, int is_float)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R2, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 4 && is_float)
|
||||
{
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
else if (size == 8)
|
||||
{
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R3, (uint32_t) writelookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
|
||||
if (size != 1) {
|
||||
host_arm_TST_IMM(block, REG_R0, size - 1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R2, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 4 && is_float) {
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||
} else if (size == 8) {
|
||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||
}
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||
if (size == 4 && is_float)
|
||||
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
|
||||
else if (size == 8)
|
||||
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t)writemembl);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t)writememwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t)writememll);
|
||||
else if (size == 8)
|
||||
host_arm_BL_r1(block, (uintptr_t)writememql);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||
*branch_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t) &block_write_data[block_pos] - (uintptr_t) misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||
if (size == 4 && is_float)
|
||||
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
|
||||
else if (size == 8)
|
||||
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t) writemembl);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t) writememwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t) writememll);
|
||||
else if (size == 8)
|
||||
host_arm_BL_r1(block, (uintptr_t) writememql);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
static void
|
||||
build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||
build_load_routine(block, 1, 0);
|
||||
codegen_mem_load_word = &block_write_data[block_pos];
|
||||
build_load_routine(block, 2, 0);
|
||||
codegen_mem_load_long = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 0);
|
||||
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 0);
|
||||
codegen_mem_load_single = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 1);
|
||||
codegen_mem_load_double = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 1);
|
||||
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||
build_load_routine(block, 1, 0);
|
||||
codegen_mem_load_word = &block_write_data[block_pos];
|
||||
build_load_routine(block, 2, 0);
|
||||
codegen_mem_load_long = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 0);
|
||||
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 0);
|
||||
codegen_mem_load_single = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 1);
|
||||
codegen_mem_load_double = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 1);
|
||||
|
||||
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||
build_store_routine(block, 1, 0);
|
||||
codegen_mem_store_word = &block_write_data[block_pos];
|
||||
build_store_routine(block, 2, 0);
|
||||
codegen_mem_store_long = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 0);
|
||||
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 0);
|
||||
codegen_mem_store_single = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 1);
|
||||
codegen_mem_store_double = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 1);
|
||||
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||
build_store_routine(block, 1, 0);
|
||||
codegen_mem_store_word = &block_write_data[block_pos];
|
||||
build_store_routine(block, 2, 0);
|
||||
codegen_mem_store_long = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 0);
|
||||
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 0);
|
||||
codegen_mem_store_single = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 1);
|
||||
codegen_mem_store_double = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 1);
|
||||
}
|
||||
|
||||
/*VFP has a specific round-to-zero instruction, and the default rounding mode
|
||||
is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/
|
||||
#define FPCSR_ROUNDING_MASK (3 << 22)
|
||||
#define FPCSR_ROUNDING_UP (1 << 22)
|
||||
#define FPCSR_ROUNDING_DOWN (2 << 22)
|
||||
# define FPCSR_ROUNDING_MASK (3 << 22)
|
||||
# define FPCSR_ROUNDING_UP (1 << 22)
|
||||
# define FPCSR_ROUNDING_DOWN (2 << 22)
|
||||
|
||||
static void build_fp_round_routine(codeblock_t *block)
|
||||
static void
|
||||
build_fp_round_routine(codeblock_t *block)
|
||||
{
|
||||
uint32_t *jump_table;
|
||||
uint32_t *jump_table;
|
||||
|
||||
codegen_alloc(block, 80);
|
||||
codegen_alloc(block, 80);
|
||||
|
||||
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
|
||||
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
|
||||
host_arm_NOP(block);
|
||||
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
|
||||
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state);
|
||||
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
|
||||
host_arm_NOP(block);
|
||||
|
||||
jump_table = (uint32_t *)&block_write_data[block_pos];
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
jump_table = (uint32_t *) &block_write_data[block_pos];
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state);
|
||||
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.old_fp_control - (uintptr_t) &cpu_state);
|
||||
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
|
||||
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero
|
||||
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
void
|
||||
codegen_backend_init(void)
|
||||
{
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
//pclog("block_pos=%i\n", block_pos);
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
// pclog("block_pos=%i\n", block_pos);
|
||||
|
||||
codegen_fp_round = &block_write_data[block_pos];
|
||||
build_fp_round_routine(&codeblock[block_current]);
|
||||
codegen_fp_round = &block_write_data[block_pos];
|
||||
build_fp_round_routine(&codeblock[block_current]);
|
||||
|
||||
codegen_alloc(block, 80);
|
||||
codegen_gpf_rout = &block_write_data[block_pos];
|
||||
host_arm_MOV_IMM(block, REG_R0, 0);
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_call(block, x86gpf);
|
||||
codegen_alloc(block, 80);
|
||||
codegen_gpf_rout = &block_write_data[block_pos];
|
||||
host_arm_MOV_IMM(block, REG_R0, 0);
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_call(block, x86gpf);
|
||||
|
||||
codegen_exit_rout = &block_write_data[block_pos];
|
||||
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||
codegen_exit_rout = &block_write_data[block_pos];
|
||||
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||
|
||||
block_write_data = NULL;
|
||||
//fatal("block_pos=%i\n", block_pos);
|
||||
asm("vmrs %0, fpscr\n"
|
||||
: "=r" (cpu_state.old_fp_control)
|
||||
);
|
||||
if ((cpu_state.old_fp_control >> 22) & 3)
|
||||
fatal("VFP not in nearest rounding mode\n");
|
||||
block_write_data = NULL;
|
||||
// fatal("block_pos=%i\n", block_pos);
|
||||
asm("vmrs %0, fpscr\n"
|
||||
: "=r"(cpu_state.old_fp_control));
|
||||
if ((cpu_state.old_fp_control >> 22) & 3)
|
||||
fatal("VFP not in nearest rounding mode\n");
|
||||
}
|
||||
|
||||
void codegen_set_rounding_mode(int mode)
|
||||
void
|
||||
codegen_set_rounding_mode(int mode)
|
||||
{
|
||||
if (mode < 0 || mode > 3)
|
||||
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||
cpu_state.new_fp_control = mode << 2;
|
||||
if (mode < 0 || mode > 3)
|
||||
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||
cpu_state.new_fp_control = mode << 2;
|
||||
}
|
||||
|
||||
/*R10 - cpu_state*/
|
||||
void codegen_backend_prologue(codeblock_t *block)
|
||||
void
|
||||
codegen_backend_prologue(codeblock_t *block)
|
||||
{
|
||||
block_pos = BLOCK_START;
|
||||
block_pos = BLOCK_START;
|
||||
|
||||
/*Entry code*/
|
||||
/*Entry code*/
|
||||
|
||||
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
|
||||
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state);
|
||||
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||
{
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
|
||||
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
|
||||
}
|
||||
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
|
||||
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t) &cpu_state);
|
||||
if (block->flags & CODEBLOCK_HAS_FPU) {
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state);
|
||||
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_backend_epilogue(codeblock_t *block)
|
||||
void
|
||||
codegen_backend_epilogue(codeblock_t *block)
|
||||
{
|
||||
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
#define HASH(l) ((l) &0x1ffff)
|
||||
|
||||
#define BLOCK_MAX 0x3c0
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
||||
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#if defined __aarch64__ || defined _M_ARM64
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/mem.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdint.h>
|
||||
# include <86box/86box.h>
|
||||
# include "cpu.h"
|
||||
# include <86box/mem.h>
|
||||
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
#include "codegen_backend_arm64_ops.h"
|
||||
#include "codegen_reg.h"
|
||||
#include "x86.h"
|
||||
#include "x87.h"
|
||||
# include "codegen.h"
|
||||
# include "codegen_allocator.h"
|
||||
# include "codegen_backend.h"
|
||||
# include "codegen_backend_arm64_defs.h"
|
||||
# include "codegen_backend_arm64_ops.h"
|
||||
# include "codegen_reg.h"
|
||||
# include "x86.h"
|
||||
# include "x87.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
# if defined(__linux__) || defined(__APPLE__)
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
# endif
|
||||
# if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# include <string.h>
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
@@ -44,334 +44,335 @@ void *codegen_fp_round_quad;
|
||||
void *codegen_gpf_rout;
|
||||
void *codegen_exit_rout;
|
||||
|
||||
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
{REG_X19, 0},
|
||||
{REG_X20, 0},
|
||||
{REG_X21, 0},
|
||||
{REG_X22, 0},
|
||||
{REG_X23, 0},
|
||||
{REG_X24, 0},
|
||||
{REG_X25, 0},
|
||||
{REG_X26, 0},
|
||||
{REG_X27, 0},
|
||||
{REG_X28, 0}
|
||||
host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS] = {
|
||||
{REG_X19, 0},
|
||||
{ REG_X20, 0},
|
||||
{ REG_X21, 0},
|
||||
{ REG_X22, 0},
|
||||
{ REG_X23, 0},
|
||||
{ REG_X24, 0},
|
||||
{ REG_X25, 0},
|
||||
{ REG_X26, 0},
|
||||
{ REG_X27, 0},
|
||||
{ REG_X28, 0}
|
||||
};
|
||||
|
||||
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
|
||||
{
|
||||
{REG_V8, 0},
|
||||
{REG_V9, 0},
|
||||
{REG_V10, 0},
|
||||
{REG_V11, 0},
|
||||
{REG_V12, 0},
|
||||
{REG_V13, 0},
|
||||
{REG_V14, 0},
|
||||
{REG_V15, 0}
|
||||
host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] = {
|
||||
{REG_V8, 0},
|
||||
{ REG_V9, 0},
|
||||
{ REG_V10, 0},
|
||||
{ REG_V11, 0},
|
||||
{ REG_V12, 0},
|
||||
{ REG_V13, 0},
|
||||
{ REG_V14, 0},
|
||||
{ REG_V15, 0}
|
||||
};
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||
static void
|
||||
build_load_routine(codeblock_t *block, int size, int is_float)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
|
||||
/*In - W0 = address
|
||||
Out - W0 = data, W1 = abrt*/
|
||||
/*MOV W1, W0, LSR #12
|
||||
MOV X2, #readlookup2
|
||||
LDR X1, [X2, X1, LSL #3]
|
||||
CMP X1, #-1
|
||||
BEQ +
|
||||
LDRB W0, [X1, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
|
||||
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X1, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 4 && is_float)
|
||||
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||
else if (size == 8)
|
||||
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||
host_arm64_MOVZ_IMM(block, REG_W1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
/*In - W0 = address
|
||||
Out - W0 = data, W1 = abrt*/
|
||||
/*MOV W1, W0, LSR #12
|
||||
MOV X2, #readlookup2
|
||||
LDR X1, [X2, X1, LSL #3]
|
||||
CMP X1, #-1
|
||||
BEQ +
|
||||
LDRB W0, [X1, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL readmembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
|
||||
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t) readlookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
|
||||
if (size != 1) {
|
||||
host_arm64_TST_IMM(block, REG_W0, size - 1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X1, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 4 && is_float)
|
||||
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||
else if (size == 8)
|
||||
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
|
||||
host_arm64_MOVZ_IMM(block, REG_W1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (void *)readmembl);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (void *)readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (void *)readmemll);
|
||||
else if (size == 8)
|
||||
host_arm64_call(block, (void *)readmemql);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
if (size == 4 && is_float)
|
||||
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
|
||||
else if (size == 8)
|
||||
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (void *) readmembl);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (void *) readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (void *) readmemll);
|
||||
else if (size == 8)
|
||||
host_arm64_call(block, (void *) readmemql);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
if (size == 4 && is_float)
|
||||
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
|
||||
else if (size == 8)
|
||||
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||
static void
|
||||
build_store_routine(codeblock_t *block, int size, int is_float)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
uint32_t *branch_offset;
|
||||
uint32_t *misaligned_offset;
|
||||
|
||||
/*In - R0 = address, R1 = data
|
||||
Out - R1 = abrt*/
|
||||
/*MOV W2, W0, LSR #12
|
||||
MOV X3, #writelookup2
|
||||
LDR X2, [X3, X2, LSL #3]
|
||||
CMP X2, #-1
|
||||
BEQ +
|
||||
STRB W1, [X2, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL writemembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
|
||||
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X2, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 4 && is_float)
|
||||
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||
else if (size == 8)
|
||||
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
/*In - R0 = address, R1 = data
|
||||
Out - R1 = abrt*/
|
||||
/*MOV W2, W0, LSR #12
|
||||
MOV X3, #writelookup2
|
||||
LDR X2, [X3, X2, LSL #3]
|
||||
CMP X2, #-1
|
||||
BEQ +
|
||||
STRB W1, [X2, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL writemembl
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
|
||||
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t) writelookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
|
||||
if (size != 1) {
|
||||
host_arm64_TST_IMM(block, REG_W0, size - 1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X2, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1 && !is_float)
|
||||
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 2 && !is_float)
|
||||
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 4 && !is_float)
|
||||
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 4 && is_float)
|
||||
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||
else if (size == 8)
|
||||
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
if (size == 4 && is_float)
|
||||
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
||||
else if (size == 8)
|
||||
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (void *)writemembl);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (void *)writememwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (void *)writememll);
|
||||
else if (size == 8)
|
||||
host_arm64_call(block, (void *)writememql);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
if (size == 4 && is_float)
|
||||
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
||||
else if (size == 8)
|
||||
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (void *) writemembl);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (void *) writememwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (void *) writememll);
|
||||
else if (size == 8)
|
||||
host_arm64_call(block, (void *) writememql);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
static void
|
||||
build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||
build_load_routine(block, 1, 0);
|
||||
codegen_mem_load_word = &block_write_data[block_pos];
|
||||
build_load_routine(block, 2, 0);
|
||||
codegen_mem_load_long = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 0);
|
||||
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 0);
|
||||
codegen_mem_load_single = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 1);
|
||||
codegen_mem_load_double = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 1);
|
||||
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||
build_load_routine(block, 1, 0);
|
||||
codegen_mem_load_word = &block_write_data[block_pos];
|
||||
build_load_routine(block, 2, 0);
|
||||
codegen_mem_load_long = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 0);
|
||||
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 0);
|
||||
codegen_mem_load_single = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 1);
|
||||
codegen_mem_load_double = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 1);
|
||||
|
||||
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||
build_store_routine(block, 1, 0);
|
||||
codegen_mem_store_word = &block_write_data[block_pos];
|
||||
build_store_routine(block, 2, 0);
|
||||
codegen_mem_store_long = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 0);
|
||||
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 0);
|
||||
codegen_mem_store_single = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 1);
|
||||
codegen_mem_store_double = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 1);
|
||||
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||
build_store_routine(block, 1, 0);
|
||||
codegen_mem_store_word = &block_write_data[block_pos];
|
||||
build_store_routine(block, 2, 0);
|
||||
codegen_mem_store_long = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 0);
|
||||
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 0);
|
||||
codegen_mem_store_single = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 1);
|
||||
codegen_mem_store_double = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 1);
|
||||
}
|
||||
|
||||
static void build_fp_round_routine(codeblock_t *block, int is_quad)
|
||||
static void
|
||||
build_fp_round_routine(codeblock_t *block, int is_quad)
|
||||
{
|
||||
uint64_t *jump_table;
|
||||
uint64_t *jump_table;
|
||||
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm64_ADR(block, REG_TEMP2, 12);
|
||||
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
|
||||
host_arm64_BR(block, REG_TEMP2);
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.new_fp_control - (uintptr_t) &cpu_state);
|
||||
host_arm64_ADR(block, REG_TEMP2, 12);
|
||||
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
|
||||
host_arm64_BR(block, REG_TEMP2);
|
||||
|
||||
jump_table = (uint64_t *)&block_write_data[block_pos];
|
||||
block_pos += 4*8;
|
||||
jump_table = (uint64_t *) &block_write_data[block_pos];
|
||||
block_pos += 4 * 8;
|
||||
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
|
||||
if (is_quad)
|
||||
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // tie even
|
||||
if (is_quad)
|
||||
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // pos inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // neg inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
|
||||
if (is_quad)
|
||||
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t) (uintptr_t) &block_write_data[block_pos]; // zero
|
||||
if (is_quad)
|
||||
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
void
|
||||
codegen_backend_init(void)
|
||||
{
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
}
|
||||
for (c = 0; c < BLOCK_SIZE; c++) {
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
}
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(block);
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(block);
|
||||
|
||||
codegen_fp_round = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 0);
|
||||
codegen_fp_round_quad = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 1);
|
||||
codegen_fp_round = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 0);
|
||||
codegen_fp_round_quad = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 1);
|
||||
|
||||
codegen_alloc(block, 80);
|
||||
codegen_gpf_rout = &block_write_data[block_pos];
|
||||
host_arm64_mov_imm(block, REG_ARG0, 0);
|
||||
host_arm64_mov_imm(block, REG_ARG1, 0);
|
||||
host_arm64_call(block, (void *)x86gpf);
|
||||
codegen_alloc(block, 80);
|
||||
codegen_gpf_rout = &block_write_data[block_pos];
|
||||
host_arm64_mov_imm(block, REG_ARG0, 0);
|
||||
host_arm64_mov_imm(block, REG_ARG1, 0);
|
||||
host_arm64_call(block, (void *) x86gpf);
|
||||
|
||||
codegen_exit_rout = &block_write_data[block_pos];
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
codegen_exit_rout = &block_write_data[block_pos];
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
block_write_data = NULL;
|
||||
block_write_data = NULL;
|
||||
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
|
||||
asm("mrs %0, fpcr\n"
|
||||
: "=r" (cpu_state.old_fp_control)
|
||||
);
|
||||
asm("mrs %0, fpcr\n"
|
||||
: "=r"(cpu_state.old_fp_control));
|
||||
}
|
||||
|
||||
void codegen_set_rounding_mode(int mode)
|
||||
void
|
||||
codegen_set_rounding_mode(int mode)
|
||||
{
|
||||
if (mode < 0 || mode > 3)
|
||||
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||
cpu_state.new_fp_control = mode << 3;
|
||||
if (mode < 0 || mode > 3)
|
||||
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||
cpu_state.new_fp_control = mode << 3;
|
||||
}
|
||||
|
||||
/*R10 - cpu_state*/
|
||||
void codegen_backend_prologue(codeblock_t *block)
|
||||
void
|
||||
codegen_backend_prologue(codeblock_t *block)
|
||||
{
|
||||
block_pos = BLOCK_START;
|
||||
block_pos = BLOCK_START;
|
||||
|
||||
/*Entry code*/
|
||||
/*Entry code*/
|
||||
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
|
||||
|
||||
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state);
|
||||
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t) &cpu_state);
|
||||
|
||||
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||
{
|
||||
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
|
||||
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
|
||||
}
|
||||
if (block->flags & CODEBLOCK_HAS_FPU) {
|
||||
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t) &cpu_state.TOP - (uintptr_t) &cpu_state);
|
||||
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
|
||||
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_backend_epilogue(codeblock_t *block)
|
||||
void
|
||||
codegen_backend_epilogue(codeblock_t *block)
|
||||
{
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
#define BLOCK_MAX 0x3c0
|
||||
#define HASH(l) ((l) &0x1ffff)
|
||||
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
||||
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||
|
||||
@@ -1,117 +1,117 @@
|
||||
#define REG_W0 0
|
||||
#define REG_W1 1
|
||||
#define REG_W2 2
|
||||
#define REG_W3 3
|
||||
#define REG_W4 4
|
||||
#define REG_W5 5
|
||||
#define REG_W6 6
|
||||
#define REG_W7 7
|
||||
#define REG_W8 8
|
||||
#define REG_W9 9
|
||||
#define REG_W10 10
|
||||
#define REG_W11 11
|
||||
#define REG_W12 12
|
||||
#define REG_W13 13
|
||||
#define REG_W14 14
|
||||
#define REG_W15 15
|
||||
#define REG_W16 16
|
||||
#define REG_W17 17
|
||||
#define REG_W18 18
|
||||
#define REG_W19 19
|
||||
#define REG_W20 20
|
||||
#define REG_W21 21
|
||||
#define REG_W22 22
|
||||
#define REG_W23 23
|
||||
#define REG_W24 24
|
||||
#define REG_W25 25
|
||||
#define REG_W26 26
|
||||
#define REG_W27 27
|
||||
#define REG_W28 28
|
||||
#define REG_W29 29
|
||||
#define REG_W30 30
|
||||
#define REG_WZR 31
|
||||
#define REG_W0 0
|
||||
#define REG_W1 1
|
||||
#define REG_W2 2
|
||||
#define REG_W3 3
|
||||
#define REG_W4 4
|
||||
#define REG_W5 5
|
||||
#define REG_W6 6
|
||||
#define REG_W7 7
|
||||
#define REG_W8 8
|
||||
#define REG_W9 9
|
||||
#define REG_W10 10
|
||||
#define REG_W11 11
|
||||
#define REG_W12 12
|
||||
#define REG_W13 13
|
||||
#define REG_W14 14
|
||||
#define REG_W15 15
|
||||
#define REG_W16 16
|
||||
#define REG_W17 17
|
||||
#define REG_W18 18
|
||||
#define REG_W19 19
|
||||
#define REG_W20 20
|
||||
#define REG_W21 21
|
||||
#define REG_W22 22
|
||||
#define REG_W23 23
|
||||
#define REG_W24 24
|
||||
#define REG_W25 25
|
||||
#define REG_W26 26
|
||||
#define REG_W27 27
|
||||
#define REG_W28 28
|
||||
#define REG_W29 29
|
||||
#define REG_W30 30
|
||||
#define REG_WZR 31
|
||||
|
||||
#define REG_X0 0
|
||||
#define REG_X1 1
|
||||
#define REG_X2 2
|
||||
#define REG_X3 3
|
||||
#define REG_X4 4
|
||||
#define REG_X5 5
|
||||
#define REG_X6 6
|
||||
#define REG_X7 7
|
||||
#define REG_X8 8
|
||||
#define REG_X9 9
|
||||
#define REG_X10 10
|
||||
#define REG_X11 11
|
||||
#define REG_X12 12
|
||||
#define REG_X13 13
|
||||
#define REG_X14 14
|
||||
#define REG_X15 15
|
||||
#define REG_X16 16
|
||||
#define REG_X17 17
|
||||
#define REG_X18 18
|
||||
#define REG_X19 19
|
||||
#define REG_X20 20
|
||||
#define REG_X21 21
|
||||
#define REG_X22 22
|
||||
#define REG_X23 23
|
||||
#define REG_X24 24
|
||||
#define REG_X25 25
|
||||
#define REG_X26 26
|
||||
#define REG_X27 27
|
||||
#define REG_X28 28
|
||||
#define REG_X29 29
|
||||
#define REG_X30 30
|
||||
#define REG_XZR 31
|
||||
#define REG_X0 0
|
||||
#define REG_X1 1
|
||||
#define REG_X2 2
|
||||
#define REG_X3 3
|
||||
#define REG_X4 4
|
||||
#define REG_X5 5
|
||||
#define REG_X6 6
|
||||
#define REG_X7 7
|
||||
#define REG_X8 8
|
||||
#define REG_X9 9
|
||||
#define REG_X10 10
|
||||
#define REG_X11 11
|
||||
#define REG_X12 12
|
||||
#define REG_X13 13
|
||||
#define REG_X14 14
|
||||
#define REG_X15 15
|
||||
#define REG_X16 16
|
||||
#define REG_X17 17
|
||||
#define REG_X18 18
|
||||
#define REG_X19 19
|
||||
#define REG_X20 20
|
||||
#define REG_X21 21
|
||||
#define REG_X22 22
|
||||
#define REG_X23 23
|
||||
#define REG_X24 24
|
||||
#define REG_X25 25
|
||||
#define REG_X26 26
|
||||
#define REG_X27 27
|
||||
#define REG_X28 28
|
||||
#define REG_X29 29
|
||||
#define REG_X30 30
|
||||
#define REG_XZR 31
|
||||
|
||||
#define REG_V0 0
|
||||
#define REG_V1 1
|
||||
#define REG_V2 2
|
||||
#define REG_V3 3
|
||||
#define REG_V4 4
|
||||
#define REG_V5 5
|
||||
#define REG_V6 6
|
||||
#define REG_V7 7
|
||||
#define REG_V8 8
|
||||
#define REG_V9 9
|
||||
#define REG_V10 10
|
||||
#define REG_V11 11
|
||||
#define REG_V12 12
|
||||
#define REG_V13 13
|
||||
#define REG_V14 14
|
||||
#define REG_V15 15
|
||||
#define REG_V16 16
|
||||
#define REG_V17 17
|
||||
#define REG_V18 18
|
||||
#define REG_V19 19
|
||||
#define REG_V20 20
|
||||
#define REG_V21 21
|
||||
#define REG_V22 22
|
||||
#define REG_V23 23
|
||||
#define REG_V24 24
|
||||
#define REG_V25 25
|
||||
#define REG_V26 26
|
||||
#define REG_V27 27
|
||||
#define REG_V28 28
|
||||
#define REG_V29 29
|
||||
#define REG_V30 30
|
||||
#define REG_V31 31
|
||||
#define REG_V0 0
|
||||
#define REG_V1 1
|
||||
#define REG_V2 2
|
||||
#define REG_V3 3
|
||||
#define REG_V4 4
|
||||
#define REG_V5 5
|
||||
#define REG_V6 6
|
||||
#define REG_V7 7
|
||||
#define REG_V8 8
|
||||
#define REG_V9 9
|
||||
#define REG_V10 10
|
||||
#define REG_V11 11
|
||||
#define REG_V12 12
|
||||
#define REG_V13 13
|
||||
#define REG_V14 14
|
||||
#define REG_V15 15
|
||||
#define REG_V16 16
|
||||
#define REG_V17 17
|
||||
#define REG_V18 18
|
||||
#define REG_V19 19
|
||||
#define REG_V20 20
|
||||
#define REG_V21 21
|
||||
#define REG_V22 22
|
||||
#define REG_V23 23
|
||||
#define REG_V24 24
|
||||
#define REG_V25 25
|
||||
#define REG_V26 26
|
||||
#define REG_V27 27
|
||||
#define REG_V28 28
|
||||
#define REG_V29 29
|
||||
#define REG_V30 30
|
||||
#define REG_V31 31
|
||||
|
||||
#define REG_XSP 31
|
||||
#define REG_XSP 31
|
||||
|
||||
#define REG_ARG0 REG_X0
|
||||
#define REG_ARG1 REG_X1
|
||||
#define REG_ARG2 REG_X2
|
||||
#define REG_ARG3 REG_X3
|
||||
#define REG_ARG0 REG_X0
|
||||
#define REG_ARG1 REG_X1
|
||||
#define REG_ARG2 REG_X2
|
||||
#define REG_ARG3 REG_X3
|
||||
|
||||
#define REG_CPUSTATE REG_X29
|
||||
#define REG_CPUSTATE REG_X29
|
||||
|
||||
#define REG_TEMP REG_X7
|
||||
#define REG_TEMP2 REG_X6
|
||||
#define REG_TEMP REG_X7
|
||||
#define REG_TEMP2 REG_X6
|
||||
|
||||
#define REG_V_TEMP REG_V0
|
||||
#define REG_V_TEMP REG_V0
|
||||
|
||||
#define CODEGEN_HOST_REGS 10
|
||||
#define CODEGEN_HOST_REGS 10
|
||||
#define CODEGEN_HOST_FP_REGS 8
|
||||
|
||||
extern void *codegen_mem_load_byte;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -251,13 +251,11 @@ void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr);
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||
|
||||
|
||||
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
|
||||
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) &7))
|
||||
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
|
||||
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1))
|
||||
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
|
||||
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
|
||||
|
||||
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) &1))
|
||||
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) &3))
|
||||
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) &7))
|
||||
|
||||
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user