Sync to DOSBox SVN r4301

This commit is contained in:
retro100 2021-02-06 16:06:31 +01:00
parent 03ba330e85
commit b4f2a13f7f
278 changed files with 22563 additions and 8449 deletions

11
COPYING
View File

@ -1,8 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
Also add information on how to contact you by electronic and paper mail.

View File

@ -1,3 +1,89 @@
0.74-3
- Implement basic file access control for files available from within
the emulation, so that programs running inside DOSBox can't access
/proc (e.g. /proc/self/mem). (CVE-2019-12594)
- Unify unmounting code and add some protections against out of bound access
when DOS_DRIVES is not 26.
- Use correct type for return value of strlen.
- Change scan3x to a bit brighter.
- Fix unitialized access to some isoDrive fields and improve stability
when switching CD images.
- Small fix to hq3x.
- Fix 256 colour mode encoding in zmbv.dll.
- Some small aliassing fix.
- Change SET to check the size of the MCB when adding variables. Fixes
hangs with Norton Commander.
- Check buffer length before doing tab completion.
- Correct buffer overflow with very long lines in bat files. (CVE-2019-7165)
- Correct the boundary check for the internal programs array.
- Increase stability in max cycles mode by increasing the lower bound.
- Fix command prompt in windows 3.11 with dynrec core.
- Fix Win64 dynrec core.
- Always clear buffers before drawing in OpenGL mode. Fixes artifacts with
drivers that have more than 2 buffers and overlays.
- Fix red border that appeared when scaling the image in OpenGL
mode with Nvidia on Linux and Mac.
- Change default output to opengl on Mac, as surface is very slow there in 64 bit.
- Add workaround for the mouse unlocking problem with X.org 1.20.1.
- Fix table access when USE_FULL_TLB is undefined (non-default configuration).
- Several fixes to prevent compilation errors.
- Update Visual studio file to fix missing files from 0.74-2.
0.74-2
- Rewrite auto/max cycles algorithm to work better with windows 7, other
OSes might benefit as well.
- Update 64bit recompiler to work on OSX and Linux.
- Several improvements to make the recompilers work with newer compilers and
add some workarounds about clang confusing itself.
- Fix several variables being the wrong size in the recompiler.
- Support absolute 64 bit addressing. (DRC:64 bit error messages)
- Zero extend data in dynrec core for LLVM compilation/
- Reduce overhead of the Mac version with a lot. Results in a speed increase.
- Replace NV_PixelDataRange with the more common ARB_PixelBufferObject
extension. Should help with output=opengl.
- Reuse graphics window if possible instead of always creating a new one!
- Add patches to work better when called by WINE:
- support WINE style namemangling.
- allow Z:\ to be moved to a different drive.
- Try to fix stuttering audio with opengl output on Linux. (or at least
improve it. Linux users might need to increase the prebuffer option a bit)
- Fix automake and autoconf problems.
- Fix problems related to packed struct layouts.
- Fix compilation on gcc 4.4 and gcc 4.6.1.
- Fix compilation with -DPIC.
- Hopefully fix crash on shutdown, when unknown condition is encountered.
- Fix -lto with gcc.
- Fix clang compliation with asm fpu core.
- Fix mapper crash on startup and when changing the mapper key.
- Fix compilation in VS2015.
- Fix compilation on mingw64.
- Fix compilation on Frisbee and newer clang.
- Fix compilation machines that have X11 libraries installed, but use a SDL
without X11.
- Fix a few problems relating to video capturing:
- Writing out the index too often. (slowdown with longer captures)
- Not being aware of when only the refresh rate changed.
- Fix call order when bitshifting the return order (VS C /O2 builds).
- Fix sign-extension error in S3 draw funcion, i.e. win3.1 analog clock.
- Fix expanddot not caring about the size of the inputbuffer.
- Some fixes for the debugger related to starting a program through debug.com.
- Bring OS/2 port code up to date.
- Reduce the amount of warning when compiling with quite a bit.
- Allow 15/26/32 bits input to the opengl output.
- Add cmd-q as exit key for macs.
- Fix icon and titlebar on very old setups.
- Fix off by one display size calculation errors with very large displays.
- Fix out of bounds access the unused byte in the 32 bit colour value of the
hardware mouse cursor pixel was affected.
- Fix depreciated warnings on Mac, allow soundfont loading for coreaudio.
- Keep repeating a pressed key if another key was unpressed.
- Fix crash on OS X related to putting junk in the titlebar.
- Extend fullresolution=0x0 to work on Linux and Mac.
- Change gameblaster and tandy sound core to latest mame version.
- Improve numlock and capslock support on Linux and Macs. Still not perfect
on Windows.
- Added even more code to workaround Windows behaving weirdly with alt-tab.
0.74
- Several small game specific fixes/hacks/support. (Offensive,
Roadhog, GTA installer, Kingdom O' Magic soundcard detection,

93
INSTALL
View File

@ -1,90 +1,97 @@
Things needed for compilation.
Things needed for compilation:
SDL
The Simple DirectMedia Library available at http://www.libsdl.org
SDL
The Simple DirectMedia Library available at https://www.libsdl.org/
The dll distributed with the windows version of DOSBox is slightly
modified. You can find the changes in the sourcepackage of DOSBox
(src/platform/sdl-win32.diff). If you want the patched sourcetree
send us an email. (see README)
Licensed under LGPL
Note that only version 1.2 and its subversions (1.2.8, 1.2.13 etc.)
are currently supported.
License: LGPLv2+
Curses (optional)
If you want to enable the debugger you need a curses library.
ncurses should be installed on just about every unix distro.
For win32 get pdcurses at http://pdcurses.sourceforge.net
License: Open source
For win32 get pdcurses at https://pdcurses.org/
License: Public Domain
Libpng (optional)
Needed for the screenshots.
For win32 get libpng from http://gnuwin32.sourceforge.net/packages.html
See http://www.libpng.org/pub/png/ for more details.
License: Open Source
License: zlib/libpng
Zlib (optional)
Needed by libpng.
For win32 get libz (rename to zlib) from http://gnuwin32.sourceforge.net/packages.html
See http://www.zlib.net for more details.
License: Open Source
See https://www.zlib.net/ for more details.
License: zlib
SDL_Net (optional)
For modem/ipx support. Get it from http://www.libsdl.org/projects/SDL_net/
Licensed under LGPL
For modem/ipx support.
Get it from https://www.libsdl.org/projects/SDL_net/release-1.2.html
License: LGPLv2+
SDL_Sound
For compressed audio on diskimages. (optional)
SDL_Sound (optional)
For compressed audio on diskimages (cue sheets) support.
This is for cue/bin cdrom images with compressed (mp3/ogg) audio tracks.
Get it from http://icculus.org/SDL_sound
Licenced under LGPL
Licence: LGPLv2+
ALSA_Headers
(optional)
ALSA_Headers (optional)
for Alsa support under linux. Part of the linux kernel sources
Licensed under LGPL
License: LGPLv2+
If you want compile from developer sources (SVN) under a unix system, you'll also need
automake (>=1.6), autoconf(>=2.50). Should be available at http://www.gnu.org
If you want compile from developer sources (SVN) under a unix system, you'll
also need automake (>=1.6) and autoconf(>=2.50).
Should be available at https://www.gnu.org/software/
For building on unix systems.
If you are building from developer sources run ./autogen.sh first before doing the following.
If you are building from developer sources run ./autogen.sh first before doing
the following:
1. ./configure
2. make
$ ./configure
$ make
In step 1 you could add the following switches:
--enable-debug
enables the internal debugger. --enable-debug=heavy enables even more
debug options. DOSBox should then be run from a xterm and when the sdl-
window is active press alt-pause to enter the debugger.
You can also run "./configure --help" for extra features to enable/disable.
Some of them are:
--enable-core-inline
enables some memory increasing inlines. This greatly increases
compiletime for maybe a increase in speed.
--enable-debug
enables the internal debugger. --enable-debug=heavy enables even more
debug options. To use the debugger, DOSBox should be run from an xterm
and when the sdl-window is active press alt-pause to enter the
debugger.
--disable-core-inline
disables some memory increasing inlines. This speeds up compilation,
but may result in a slower dosbox.
--disable-fpu
disables the emulated fpu. Although the fpu emulation code isn't
finished and isn't entirely accurate it's advised to leave it on.
disables the emulated fpu. Although the fpu emulation code isn't
finished and isn't entirely accurate, it's advised to leave it on.
--disable-fpu-x86
disables the assembly fpu core. Although relatively new the x86 fpu
core has more accuracy then the regular fpu core.
--disable-fpu-x64
disables the assembly fpu core. Although relatively new, the x86/x64
fpu core has more accuracy than the regular fpu core.
--disable-dynamic-x86
disables the dynamic x86 specific cpu core. Although it might be
be a bit unstable, it can greatly improve the speed of dosbox on x86
hosts.
Please note that this option on x86 will result in a different
dynamic/recompiling cpu core being compiled then the default.
disables the dynamic x86/x64 specific cpu core. Although it might be
a bit unstable, it can greatly improve the speed of dosbox on x86 and
x64 hosts.
Please note that this option on x86/x64 will result in a different
dynamic/recompiling cpu core being compiled than the default.
For more information see the option --disable-dynrec
--disable-dynrec
disables the recompiling cpu core. Currently x86 and x86_64 only.
You can activate this core on x86 by disabling the dynamic-x86 core.
disables the recompiling cpu core. Currently x86/x64 and arm only.
You can activate this core on x86/x64 by disabling the dynamic-x86
core.
--disable-dynamic-core
disables all dynamic cores. (same effect as
--disable-dynamic-x86 --disable-dynrec)
disables all dynamic cores (same effect as --disable-dynamic-x86
or --disable-dynrec).
--disable-opengl
disables OpenGL-support (output mode that can be selected in the

View File

@ -18,7 +18,8 @@ include $(DEVKITPPC)/wii_rules
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := src src/cpu src/debug src/dos src/fpu src/gui \
src/hardware src/hardware/serialport src/ints src/libs \
src/hardware src/hardware/mame \
src/hardware/serialport src/ints src/libs \
src/misc src/platform/wii src/platform/wii/fonts \
src/platform/wii/images src/platform/wii/libwiigui \
src/platform/wii/sounds src/shell

26
NEWS
View File

@ -1,3 +1,29 @@
0.74-3
A security release for DOSBox 0.74:
- Fixed that a very long line inside a bat file would overflow the parsing
buffer (CVE-2019-7165 by Alexandre Bartel)
- Added a basic permission system so that a program running inside DOSBox
can't access the contents of /proc (e.g. /proc/self/mem) when / or /proc
were (to be) mounted (CVE-2019-12594 by Alexandre Bartel)
- Several other fixes for out of bounds access and buffer overflows.
- Some fixes to the OpenGL rendering.
It's recommended to use config -securemode when dealing with untrusted
files.
See the Changelog for all the changes.
0.74-2
A maintenance release for DOSBox 0.74, which solves the following problems:
- Windows: Fix auto/max cycles algorithm on Windows 7, which helps with
stuttering audio.
- Mac OS X: Bring a 64 bit version and improve performance.
- Linux: Fix the 64bit dynrec cpu core and a lot of compilation problems.
Add patches for the WINE Team.
The game compatibility should be identical to 0.74.
See the Changelog for a full list of changes.
0.74
- Several small game specific fixes/hacks/support. (Offensive,
Roadhog, GTA installer, Kingdom O' Magic soundcard detection,

48
README
View File

@ -22,6 +22,7 @@ A port of DOSBox to the Wii using SDL Wii.
[current master - 2021]
* Updated to latest libogc and devkitPPC
* Convert CRLF line terminators to unix line terminators (like at original SVN repo)
* Sync to DOSBox SVN r4301
[1.7 - June 30, 2012]
@ -112,7 +113,7 @@ you want to play on the PC version of DOSBox first to discover the optimum
settings.
-------------------------------------------------------------------------------
DOSBox v0.74 Manual (always use the latest version from www.dosbox.com)
DOSBox v0.74-2 Manual (always use the latest version from www.dosbox.com)
@ -161,7 +162,7 @@ It is essential that you get familiar with the idea of mounting, DOSBox does not
automatically make any drive (or a part of it) accessible to the emulation. See
the FAQ entry "How to start?" as well as the description of the MOUNT command
(Section 4: "Internal Programs"). If you have your game on a cdrom you may try
this guide: http://vogons.zetafleet.com/viewtopic.php?t=8933
this guide: https://www.vogons.org/viewtopic.php?t=8933
@ -172,6 +173,7 @@ this guide: http://vogons.zetafleet.com/viewtopic.php?t=8933
START: How to start?
AUTOMATION: Do I always have to type these "mount" commands?
FULLSCREEN: How do I change to fullscreen?
FULLSCREEN: My fullscreen is too large.
CD-ROM: My CD-ROM doesn't work.
CD-ROM: The game/application can't find its CD-ROM.
MOUSE: The mouse doesn't work.
@ -217,6 +219,26 @@ FULLSCREEN: How do I change to fullscreen?
mode: Press alt-enter again.
FULLSCREEN: My fullscreen is too large.
This is can be a problem on Windows 10, if you have display scaling
set to a value above 100%. Windows in that case will resize the screen
on top of dosbox resizing the screen, which can happen for the output:
ddraw, opengl, openglnb, overlay. You can disable this Windows behaviour
by enabling a specific compatibility setting:
- Right-click the DOSBox icon and select "Properties".
- Go to the "Compatibility" tab.
- Click on "Change high DPI settings".
- Tick "Override high DPI scaling behaviour" and set it to "Application".
- Apply the changes by clicking on "OK".
Unfortunately, this compatibility option causes some side effects in
windowed mode, and in this case you will need to change the resolution
in the config/Options file for windowresolution (e.g. 1024x768).
Alternatively, you can disable the display scaling and or use a lower
fullresolution value.
CD-ROM: My CD-ROM doesn't work.
To mount your CD-ROM in DOSBox you have to specify some additional options
when mounting the CD-ROM.
@ -370,7 +392,7 @@ KEYBOARD: Right Shift and "\" doesn't work in DOSBox. (Windows only)
dosbox.exe
check whether keyboard started to work properly. As windib is slower it is
best to use one of the two solutions provided here:
http://vogons.zetafleet.com/viewtopic.php?t=24072
https://www.vogons.org/viewtopic.php?t=24072
KEYBOARD: The keyboard lags.
@ -422,9 +444,9 @@ OPTIONS: I would like to change DOSBox's options.
HELP: Great Manual, but I still don't get it.
For more questions read the rest of this Manual. You may also look at:
guides located at http://vogons.zetafleet.com/viewforum.php?f=39
the wiki of DOSBox http://www.dosbox.com/wiki/
the site/forum: http://www.dosbox.com
guides located at https://www.vogons.org/viewforum.php?f=53
the wiki of DOSBox https://www.dosbox.com/wiki/
the site/forum: https://www.dosbox.com
@ -1132,7 +1154,7 @@ KEYB [keyboardlayoutcode [codepage [codepagefile]]]
examples are PL214 (Polish typists) or PL457 (Polish programmers).
It specifies the keyboard layout to be used.
The list of all layouts built into DOSBox is here:
http://vogons.zetafleet.com/viewtopic.php?t=21824
https://www.vogons.org/viewtopic.php?t=21824
[codepage] is the number of the codepage to be used. The keyboard layout
has to provide support for the specified codepage, otherwise the layout
@ -1211,7 +1233,7 @@ if the key doesn't work i.e. fn-cmd-ctrl-F1, but some keys may still need
remapping (in Linux too).
Saved/recorded files can be found in:
(Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Extras
(Windows) "Start/WinLogo Menu"->"All Programs"->"DOSBox-0.74-2"->Extras
(Linux) ~/.dosbox/capture
(Mac OS X) "~/Library/Preferences/capture"
This can be changed in the DOSBox configuration file.
@ -1366,7 +1388,7 @@ Layout switching
in this case just the layout identifier needs to be specified (like
keyboardlayout=PL214 in the DOSBox configuration file, or using "keyb PL214"
at the DOSBox command prompt). The list of all layouts built into DOSBox is
here: http://vogons.zetafleet.com/viewtopic.php?t=21824
here: https://www.vogons.org/viewtopic.php?t=21824
Some keyboard layouts (for example layout GK319 codepage 869 and layout RU441
codepage 808) have support for dual layouts that can be accessed by pressing
@ -1601,9 +1623,9 @@ To display the DOSBox status window:
The configuration file is automatically created the first time you run DOSBox.
The file can be found in:
(Windows) "Start/WinLogo Menu"->"All Programs"->DOSBox-0.74->Options
(Linux) ~/.dosbox/dosbox-0.74.conf
(Mac OS X) "~/Library/Preferences/DOSBox 0.74 Preferences"
(Windows) "Start/WinLogo Menu"->"All Programs"->"DOSBox-0.74-2"->Options
(Linux) ~/.dosbox/dosbox-0.74-2.conf
(Mac OS X) "~/Library/Preferences/DOSBox 0.74-2 Preferences"
The file is divided into several sections. Each section starts with a
[section name] line. The settings are the property=value lines where value can
be altered to customize DOSBox.
@ -1664,7 +1686,7 @@ See the THANKS file.
============
See the site:
http://www.dosbox.com
https://www.dosbox.com
for an email address (The Crew-page).

View File

@ -1 +1 @@
0.74
0.74-2

View File

@ -144,7 +144,7 @@ int main (int argc, char *argv[])
echo "*** If you have an old version installed, it is best to remove it, although"
echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
[ echo "*** The test program failed to compile or link. See the file config.log for the"
echo "*** exact error that occured. This usually means SDL was incorrectly installed"
echo "*** exact error that occurred. This usually means SDL was incorrectly installed"
echo "*** or that you have moved SDL since it was installed. In the latter case, you"
echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
CFLAGS="$ac_save_CFLAGS"
@ -305,7 +305,7 @@ AC_SUBST(ALSA_LIBS)
AH_TOP([
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -317,9 +317,9 @@ AH_TOP([
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
])
@ -370,29 +370,41 @@ typedef double Real64;
#if SIZEOF_UNSIGNED_INT == 4
typedef unsigned int Bit32u;
typedef signed int Bit32s;
#define sBit32t
#elif SIZEOF_UNSIGNED_LONG == 4
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#define sBit32t "l"
#else
# error "can't find sizeof(type) of 4 bytes!"
#endif
#define sBit32fs(a) sBit32t #a
#if SIZEOF_UNSIGNED_LONG == 8
typedef unsigned long Bit64u;
typedef signed long Bit64s;
#define sBit64t "l"
#elif SIZEOF_UNSIGNED_LONG_LONG == 8
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#define sBit64t "ll"
#else
# error "can't find data type of 8 bytes"
#endif
#define sBit64fs(a) sBit64t #a
#if SIZEOF_INT_P == 4
typedef Bit32u Bitu;
typedef Bit32s Bits;
#else
typedef Bit64u Bitu;
typedef Bit64s Bits;
typedef Bit32u Bitu;
typedef Bit32s Bits;
#define sBitfs sBit32fs
#else //SIZEOF_INT_P
typedef Bit64u Bitu;
typedef Bit64s Bits;
#define sBitfs sBit64fs
#endif
])

0
autogen.sh Normal file → Executable file
View File

View File

@ -9,7 +9,7 @@ AC_CANONICAL_BUILD
dnl Setup for automake
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(config.h)
AC_CONFIG_HEADER(config.h)
dnl Checks for programs.
AC_PROG_MAKE_SET
@ -24,7 +24,6 @@ dnl perharps join this with the other target depended checks. move them upwards
if test x$host = xi386-pc-os2-emx ; then
CXXFLAGS="$CXXFLAGS -Zmt"
LDFLAGS="$LDFLAGS -Zomf -Zmt"
LIBS="$LIBS -los2me"
fi
dnl Check for SDL
@ -129,11 +128,17 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <math.h>]],[[
]])], [AC_MSG_RESULT(yes)], [AC_DEFINE([DB_HAVE_NO_POWF],[1],[libm doesn't include powf])])
LIBS=$LIBS_BACKUP
dnl Look for clock_gettime, a DB_HAVE_CLOCK_GETTIME is set when present
AH_TEMPLATE([DB_HAVE_CLOCK_GETTIME],[Determines if the function clock_gettime is available.])
AC_SEARCH_LIBS([clock_gettime], [rt] , [found_clock_gettime=yes], [found_clock_gettime=no])
if test x$found_clock_gettime = xyes; then
AC_DEFINE(DB_HAVE_CLOCK_GETTIME)
fi
dnl Checks for libraries.
#Check if the compiler support attributes
AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compilers supports attributes for structures.])
AH_TEMPLATE([C_HAS_ATTRIBUTE],[Determines if the compiler supports attributes for structures.])
AC_MSG_CHECKING(if compiler allows __attribute__)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
typedef struct { } __attribute__((packed)) junk;]],
@ -144,12 +149,12 @@ typedef struct { } __attribute__((packed)) junk;]],
OLDCFLAGS="$CFLAGS"
CFLAGS="-Werror"
AH_TEMPLATE([C_ATTRIBUTE_ALWAYS_INLINE],[Determines if the compilers supports always_inline attribute.])
AH_TEMPLATE([C_ATTRIBUTE_ALWAYS_INLINE],[Determines if the compiler supports always_inline attribute.])
AC_MSG_CHECKING(if compiler allows __attribute__((always_inline)) )
AC_COMPILE_IFELSE([AC_LANG_SOURCE([ void __attribute__((always_inline)) test(){}
AC_COMPILE_IFELSE([AC_LANG_SOURCE([ inline void __attribute__((always_inline)) test(){}
])],[ AC_MSG_RESULT(yes);AC_DEFINE(C_ATTRIBUTE_ALWAYS_INLINE)],AC_MSG_RESULT(no))
AH_TEMPLATE([C_ATTRIBUTE_FASTCALL],[Determines if the compilers supports fastcall attribute.])
AH_TEMPLATE([C_ATTRIBUTE_FASTCALL],[Determines if the compiler supports fastcall attribute.])
AC_MSG_CHECKING(if compiler allows __attribute__((fastcall)) )
AC_COMPILE_IFELSE([AC_LANG_SOURCE([ void __attribute__((fastcall)) test(){}
])],[ AC_MSG_RESULT(yes);AC_DEFINE(C_ATTRIBUTE_FASTCALL)],AC_MSG_RESULT(no))
@ -169,6 +174,48 @@ int x=10;if( __builtin_expect ((x==1),0) ) ;
#switch language back
AC_LANG_POP(C++)
dnl test if compiler supports -mno-ms-bitfields as it is bugged
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
BACKUP_CFLAGS="$CFLAGS"
CFLAGS="-mno-ms-bitfields"
AC_MSG_CHECKING(if compiler supports -mno-ms-bitfields)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void blah(){
;
}
])],[
AC_MSG_RESULT([yes])
CXXFLAGS="$CXXFLAGS -mno-ms-bitfields"
],[AC_MSG_RESULT([no])])
CFLAGS="$BACKUP_CFLAGS"
dnl When on macOS, enable support for Apple's Core MIDI and/or Core Audio if our compiler can #include their headers
case "$host" in
*-*-darwin*)
AC_MSG_CHECKING(if compiler supports Apple's Core MIDI headers)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <CoreMIDI/MIDIServices.h>
int blah() { return 0; }
]])], [AC_MSG_RESULT(yes);LIBS="$LIBS -framework CoreMIDI";AC_DEFINE([C_SUPPORTS_COREMIDI], [],
[Compiler supports Core MIDI headers])],
AC_MSG_RESULT(no);AC_MSG_WARN([Compiler can't compile Apple headers. CoreMIDI functionality disabled. Please use the Apple compiler!]))
AC_MSG_CHECKING(if compiler supports Apple's Core Audio headers)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <AudioToolbox/AUGraph.h>
#include <CoreServices/CoreServices.h>
int blah() { return 0; }
]])], [AC_MSG_RESULT(yes);LIBS="$LIBS -framework AudioUnit -framework AudioToolbox";AC_DEFINE([C_SUPPORTS_COREAUDIO], [],
[Compiler supports Core Audio headers])],
AC_MSG_RESULT(no);AC_MSG_WARN([Compiler can't compile Apple headers. CoreAudio functionality disabled. Please use the Apple compiler!]))
;;
*)
AC_MSG_CHECKING(if compiler supports Apple's MIDI headers)
AC_MSG_RESULT([no, not on Apple])
;;
esac
dnl enable disable alsa and pass it's cflags to CXXFLAGS
AC_ARG_ENABLE(alsa-midi,
AC_HELP_STRING([--enable-alsa-midi],[compile with alsa midi support (default yes)]),
@ -196,14 +243,14 @@ AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[
if test x$enable_debug = xno; then
AC_MSG_RESULT([Debugger not enabled])
elif test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then
LIBS="$LIBS -lcurses"
elif test x$have_ncurses_lib = xyes -a x$have_curses_h = xyes ; then
LIBS="$LIBS -lncurses"
AC_DEFINE(C_DEBUG,1)
if test x$enable_debug = xheavy ; then
AC_DEFINE(C_HEAVY_DEBUG,1)
fi
elif test x$have_ncurses_lib = xyes -a x$have_curses_h = xyes ; then
LIBS="$LIBS -lncurses"
elif test x$have_curses_lib = xyes -a x$have_curses_h = xyes ; then
LIBS="$LIBS -lcurses"
AC_DEFINE(C_DEBUG,1)
if test x$enable_debug = xheavy ; then
AC_DEFINE(C_HEAVY_DEBUG,1)
@ -220,13 +267,14 @@ AC_ARG_ENABLE(debug,AC_HELP_STRING([--enable-debug],[Enable debug mode]),[
],)
AH_TEMPLATE(C_CORE_INLINE,[Define to 1 to use inlined memory functions in cpu core])
AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined memory handling in CPU Core]),[
if test x$enable_core_inline = xyes ; then
AC_MSG_RESULT([enabling inlined memory handling in CPU Core])
AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--disable-core-inline],[Disable inlined memory handling in CPU Core]),,enable_core_inline=yes)
AC_MSG_CHECKING(whether memory handling in the CPU Core will be inlined)
if test x$enable_core_inline = xyes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(C_CORE_INLINE,1)
fi
],)
else
AC_MSG_RESULT(no)
fi
dnl The target cpu checks for dynamic cores
AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has])
@ -256,6 +304,24 @@ case "$host_cpu" in
c_targetcpu="m68k"
c_unalignedmemory=yes
;;
armv7l)
AC_DEFINE(C_TARGETCPU,ARMV7LE)
AC_MSG_RESULT(ARMv7 Little Endian)
c_targetcpu="arm"
c_unalignedmemory=yes
;;
armv6l)
AC_DEFINE(C_TARGETCPU,ARMV4LE)
AC_MSG_RESULT(ARMv6 Little Endian)
c_targetcpu="arm"
dnl c_unalignedmemory=yes
;;
aarch64)
AC_DEFINE(C_TARGETCPU,ARMV8LE)
AC_MSG_RESULT(ARMv8 Little Endian 64-bit)
c_targetcpu="arm"
c_unalignedmemory=yes
;;
*)
AC_DEFINE(C_TARGETCPU,UNKNOWN)
AC_MSG_RESULT(unknown)
@ -263,15 +329,45 @@ case "$host_cpu" in
;;
esac
dnl check for size of pointer being 4
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#if SIZEOF_INT_P != 4
#error size intp is not 4, this not something to worry about
#endif
void blah() {
;
}
])],[c_sizep=4],[c_sizep=0])
dnl automake 1.14 and upwards rewrite the host to have always 64 bit unless i386 as host is passed
dnl this can make building a 32 bit executable a bit tricky, as dosbox relies on the host to select the
dnl dynamic/dynrec core
AC_MSG_CHECKING([whether Apple user wants to override the build process to produce a 32 bit binary])
case "$host" in
*-*-darwin*)
if test x$c_targetcpu = xx86_64 -a x$c_sizep = x4 ; then
AC_MSG_RESULT(yes)
AC_DEFINE(C_TARGETCPU,X86)
c_targetcpu="x86"
else
AC_MSG_RESULT(no)
fi
;;
*)
AC_MSG_RESULT([no, not on Apple])
;;
esac
AC_ARG_ENABLE(dynamic-core,AC_HELP_STRING([--disable-dynamic-core],[Disable all dynamic cores]),,enable_dynamic_core=yes)
AH_TEMPLATE(C_DYNAMIC_X86,[Define to 1 to use x86 dynamic cpu core])
AC_ARG_ENABLE(dynamic-x86,AC_HELP_STRING([--disable-dynamic-x86],[Disable x86 dynamic cpu core]),,enable_dynamic_x86=yes)
AH_TEMPLATE(C_DYNAMIC_X86,[Define to 1 to use x86/x64 dynamic cpu core])
AC_ARG_ENABLE(dynamic-x86,AC_HELP_STRING([--disable-dynamic-x86],[Disable x86/x64 dynamic cpu core]),,enable_dynamic_x86=yes)
AC_MSG_CHECKING(whether x86 dynamic cpu core will be enabled)
if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
if test x$c_targetcpu = xx86 ; then
if test x$c_targetcpu = xx86 -o x$c_targetcpu = xx86_64; then
AC_DEFINE(C_DYNAMIC_X86,1)
AC_MSG_RESULT(yes)
else
@ -286,7 +382,7 @@ if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then
AC_MSG_RESULT(no)
else
dnl x86 only enable it if dynamic-x86 is disabled.
if test x$c_targetcpu = xx86 ; then
if test x$c_targetcpu = xx86 -o x$c_targetcpu = xx86_64; then
if test x$enable_dynamic_x86 = xno ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
@ -294,10 +390,10 @@ dnl x86 only enable it if dynamic-x86 is disabled.
AC_MSG_RESULT([no, using dynamic-x86])
fi
else
if test x$c_targetcpu = xx86_64 ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
if test x$c_targetcpu = xarm ; then
AC_DEFINE(C_DYNREC,1)
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
fi
@ -313,14 +409,15 @@ else
AC_MSG_RESULT(no)
fi
AH_TEMPLATE(C_FPU_X86,[Define to 1 to use a x86 assembly fpu core])
AH_TEMPLATE(C_FPU_X86,[Define to 1 to use a x86/x64 assembly fpu core])
AC_ARG_ENABLE(fpu-x86,AC_HELP_STRING([--disable-fpu-x86],[Disable x86 assembly fpu core]),,enable_fpu_x86=yes)
AC_MSG_CHECKING(whether x86 assembly fpu core will be enabled)
if test x$enable_fpu_x86 = xno ; then
AC_ARG_ENABLE(fpu-x64,AC_HELP_STRING([--disable-fpu-x64],[Disable x64 assembly fpu core]),,enable_fpu_x64=yes)
AC_MSG_CHECKING(whether the x86/x64 assembly fpu core will be enabled)
if test x$enable_fpu_x86 = xno -o x$enable_fpu_x64 = xno; then
AC_MSG_RESULT(no)
else
if test x$enable_fpu = xyes; then
if test x$c_targetcpu = xx86 ; then
if test x$c_targetcpu = xx86 -o x$c_targetcpu = xx86_64; then
AC_DEFINE(C_FPU_X86,1)
AC_MSG_RESULT(yes)
else
@ -342,13 +439,20 @@ else
fi
AH_TEMPLATE(C_SSHOT,[Define to 1 to enable screenshots, requires libpng])
AC_ARG_ENABLE(screenshots,AC_HELP_STRING([--disable-screenshots],[Disable screenshots and movie recording]),,enable_screenshots=yes)
AC_CHECK_HEADER(png.h,have_png_h=yes,)
AC_CHECK_LIB(png, png_get_io_ptr, have_png_lib=yes, ,-lz)
if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then
LIBS="$LIBS -lpng -lz"
AC_DEFINE(C_SSHOT,1)
AC_MSG_CHECKING([whether screenshots will be enabled])
if test x$enable_screenshots = xyes; then
if test x$have_png_lib = xyes -a x$have_png_h = xyes ; then
LIBS="$LIBS -lpng -lz"
AC_DEFINE(C_SSHOT,1)
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no, can't find libpng.])
fi
else
AC_MSG_WARN([Can't find libpng, screenshot support disabled])
AC_MSG_RESULT([no])
fi
AH_TEMPLATE(C_MODEM,[Define to 1 to enable internal modem support, requires SDL_net])
@ -413,6 +517,28 @@ case "$host" in
fi
;;
esac
else
AC_MSG_RESULT(no)
fi
AH_TEMPLATE(C_DDRAW,[Define to 1 to enable output=ddraw (Win32)])
AC_ARG_ENABLE(ddraw,AC_HELP_STRING([--disable-ddraw],[Disable ddraw support]),,enable_ddraw=yes)
AC_CHECK_HEADER(ddraw.h, have_ddraw_h=yes , have_ddraw_h=no , )
AC_MSG_CHECKING(whether ddraw display output will be enabled)
if test x$enable_ddraw = xyes; then
case "$host" in
*-*-cygwin* | *-*-mingw32*)
if test x$have_ddraw_h = xyes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(C_DDRAW,1)
else
AC_MSG_RESULT(no)
fi
;;
*)
AC_MSG_RESULT(no)
;;
esac
fi
AH_TEMPLATE(C_SDL_SOUND,[Define to 1 to enable SDL_sound support])
@ -436,6 +562,9 @@ AC_CHECK_HEADER([sys/mman.h], [
AC_CHECK_FUNC([mprotect],[AC_DEFINE(C_HAVE_MPROTECT,1)])
])
dnl Check for realpath. Used on Linux
AC_CHECK_FUNCS([realpath])
dnl Setpriority
AH_TEMPLATE(C_SET_PRIORITY,[Define to 1 if you have setpriority support])
AC_MSG_CHECKING(for setpriority support)
@ -451,7 +580,6 @@ dnl Some target detection and actions for them
case "$host" in
*-*-cygwin* | *-*-mingw32*)
LIBS="$LIBS -lwinmm"
AC_CHECK_HEADERS(ddraw.h)
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2 only).])
if test x$have_sdl_net_lib = xyes -a x$have_sdl_net_h = xyes ; then
LIBS="$LIBS -lws2_32"
@ -463,7 +591,6 @@ case "$host" in
dnl to do more to distinguish them.
dnl For now I am lazy and do not add proper detection code.
AC_DEFINE(MACOSX, 1, [Compiling on Mac OS X])
LIBS="$LIBS -framework CoreMIDI -framework AudioUnit -framework AudioToolbox"
AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).])
;;
*-*-linux*)
@ -512,6 +639,7 @@ src/dos/Makefile
src/fpu/Makefile
src/gui/Makefile
src/hardware/Makefile
src/hardware/mame/Makefile
src/hardware/serialport/Makefile
src/ints/Makefile
src/libs/Makefile

View File

@ -32,4 +32,4 @@ A: 1. Start DOSBox like this: dosbox -startmapper
selected.
Q: The colours are wrong and I'm using 64 bit windows
A: Look here: http://vogons.zetafleet.com/viewtopic.php?t=12133
A: Look here: https://www.vogons.org/viewtopic.php?t=12133

View File

@ -1,5 +1,5 @@
.\" Hey, EMACS: -*- nroff -*-
.TH DOSBOX 1 "Feb 26, 2010"
.TH DOSBOX 1 "Sep 08, 2015"
.\" Please adjust this date whenever revising the manpage.
.SH NAME
dosbox \- an x86/DOS emulator with sound/graphics
@ -14,10 +14,11 @@ dosbox \- an x86/DOS emulator with sound/graphics
.BI "[\-forcescaler " scaler ]
.BI "[\-conf " configfile ]
.BI "[\-lang " langfile ]
.B [file]
.BI "[\-machine " machinetype ]
.BI "[\-socket " socketnumber ]
.BI "[\-c " command ]
.B [\-exit]
.BI "[\-machine " machinetype ]
.B [file]
.LP
.B dosbox \-version
.LP
@ -76,6 +77,25 @@ file for the available scalers
.RB "Similar to the " \-scaler " parameter, but tries to force usage of"
the specified scaler even if it might not fit.
.TP
.BI \-conf " configfile"
.RB "Start " dosbox " with the options specified in "
.IR configfile ". This file has a section in which you can put commands you "
wish to execute on startup. Multiple
.IR configfiles " can be present at the commandline."
.TP
.BI \-lang " langfile"
.RB "Start " dosbox " with the language specified in "
.IR langfile .
.TP
.BI \-machine " machinetype"
.RB "Setup " dosbox " to emulate a specific type of machine."
.RI "Valid choices are: " "hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3(default), svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe".
The machinetype has influence on both the videocard and the available
soundcards.
.TP
.BI \-socket " socketnumber"
.RI "Passes the socket number " socketnumber " to the nullmodem emulation. See README for details."
.TP
.BI \-c " command"
.RI "Runs the specified " command " before running "
.BR file .
@ -83,25 +103,9 @@ the specified scaler even if it might not fit.
.BR \-c " though. A command can be:"
an Internal Program, a DOS command or an executable on a mounted drive.
.TP
.BI \-conf " configfile
.RB "Start " dosbox " with the options specified in "
.IR configfile ". This file has a section in which you can put commands you "
wish to execute on startup. Multiple
.IR configfiles " can be present at the commandline."
.TP
.BI \-lang " langfile
.RB "Start " dosbox " with the language specified in "
.IR langfile .
.TP
.B "\-exit "
.BR "dosbox" " will close itself when the DOS program specified by "file " ends."
.TP
.BI \-machine " machinetype
.RB "Setup " dosbox " to emulate a specific type of machine."
.RI "Valid choices are: " "hercules, cga, tandy, pcjr, ega, vgaonly, svga_s3(default), svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe".
The machinetype has influence on both the videocard and the available
soundcards.
.TP
.B \-version
Output version information and exit. Useful for frontends.
.TP

View File

@ -20,8 +20,8 @@ keyboard.h \
logging.h \
mapper.h \
mem.h \
midi.h \
mixer.h \
modules.h \
mouse.h \
paging.h \
pci_bus.h \

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_BIOS_H
@ -61,6 +61,7 @@
#define BIOS_VDU_CONTROL 0x465
#define BIOS_VDU_COLOR_REGISTER 0x466
/* 0x467-0x468 is reserved */
#define BIOS_LAST_UNEXPECTED_IRQ 0x46b
#define BIOS_TIMER 0x46c
#define BIOS_24_HOURS_FLAG 0x470
#define BIOS_KEYBOARD_FLAGS 0x471
@ -103,6 +104,7 @@
#define BIOS_DEFAULT_HANDLER_LOCATION (RealMake(0xf000,0xff53))
#define BIOS_DEFAULT_INT5_LOCATION (RealMake(0xf000,0xff54))
#define BIOS_DEFAULT_IRQ0_LOCATION (RealMake(0xf000,0xfea5))
#define BIOS_DEFAULT_IRQ1_LOCATION (RealMake(0xf000,0xe987))
#define BIOS_DEFAULT_IRQ2_LOCATION (RealMake(0xf000,0xff55))

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_BIOS_DISK_H
@ -54,18 +54,20 @@ public:
void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
Bit8u GetBiosType(void);
Bit32u getSectSize(void);
imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
imageDisk(FILE *imgFile, const char *imgName, Bit32u imgSizeK, bool isHardDisk);
~imageDisk() { if(diskimg != NULL) { fclose(diskimg); } };
bool hardDrive;
bool active;
FILE *diskimg;
Bit8u diskname[512];
char diskname[512];
Bit8u floppytype;
Bit32u sector_size;
Bit32u heads,cylinders,sectors;
private:
Bit32u current_fpos;
enum { NONE,READ,WRITE } last_action;
};
void updateDPT(void);
@ -73,9 +75,11 @@ void incrementFDD(void);
#define MAX_HDD_IMAGES 2
extern imageDisk *imageDiskList[2 + MAX_HDD_IMAGES];
extern imageDisk *diskSwap[20];
extern Bits swapPosition;
#define MAX_DISK_IMAGES (2 + MAX_HDD_IMAGES)
extern imageDisk *imageDiskList[MAX_DISK_IMAGES];
extern imageDisk *diskSwap[MAX_SWAPPABLE_DISKS];
extern Bit32s swapPosition;
extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
extern DOS_DTA *imgDTA;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -27,10 +27,11 @@
typedef Bitu (*CallBack_Handler)(void);
extern CallBack_Handler CallBack_Handlers[];
enum { CB_RETN,CB_RETF,CB_RETF8,CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
enum { CB_RETN,CB_RETF,CB_RETF8,CB_RETF_STI,CB_RETF_CLI,
CB_IRET,CB_IRETD,CB_IRET_STI,CB_IRET_EOI_PIC1,
CB_IRQ0,CB_IRQ1,CB_IRQ9,CB_IRQ12,CB_IRQ12_RET,CB_IRQ6_PCJR,CB_MOUSE,
CB_INT29,CB_INT16,CB_HOOKABLE,CB_TDE_IRET,CB_IPXESR,CB_IPXESR_RET,
CB_INT21,CB_INT13 };
CB_INT21,CB_INT13,CB_VESA_WAIT,CB_VESA_PM };
#define CB_MAX 128
#define CB_SIZE 32

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -37,7 +37,7 @@
#define CPU_AUTODETERMINE_SHIFT 0x02
#define CPU_AUTODETERMINE_MASK 0x03
#define CPU_CYCLES_LOWER_LIMIT 100
#define CPU_CYCLES_LOWER_LIMIT 200
#define CPU_ARCHTYPE_MIXED 0xff
@ -71,6 +71,7 @@ extern CPU_Decoder * cpudecoder;
Bits CPU_Core_Normal_Run(void);
Bits CPU_Core_Normal_Trap_Run(void);
Bits CPU_Core_Simple_Run(void);
Bits CPU_Core_Simple_Trap_Run(void);
Bits CPU_Core_Full_Run(void);
Bits CPU_Core_Dyn_X86_Run(void);
Bits CPU_Core_Dyn_X86_Trap_Run(void);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -105,4 +105,5 @@ bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_dire
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory);
void close_directory(dir_information* dirp);
FILE *fopen_wrap(const char *path, const char *mode);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
void DEBUG_SetupConsole(void);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -24,7 +24,7 @@ enum DMAEvent {
DMA_REACHED_TC,
DMA_MASKED,
DMA_UNMASKED,
DMA_TRANSFEREND
// DMA_TRANSFEREND, this shouldn't really be a ignal
};
class DmaChannel;
@ -86,8 +86,8 @@ private:
bool flipflop;
DmaChannel *DmaChannels[4];
public:
IO_ReadHandleObject DMA_ReadHandler[0x11];
IO_WriteHandleObject DMA_WriteHandler[0x11];
IO_ReadHandleObject DMA_ReadHandler[0x12];
IO_WriteHandleObject DMA_WriteHandler[0x12];
DmaController(Bit8u num) {
flipflop = false;
ctrlnum = num; /* first or second DMA controller */
@ -115,6 +115,4 @@ bool SecondDMAControllerAvailable(void);
void DMA_SetWrapping(Bitu wrap);
static Bit32u dma_wrapping = 0xffff;
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -110,19 +110,19 @@ enum { HAND_NONE=0,HAND_FILE,HAND_DEVICE};
/* Routines for File Class */
void DOS_SetupFiles (void);
bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount);
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type);
bool DOS_CloseFile(Bit16u handle);
bool DOS_ReadFile(Bit16u handle,Bit8u * data,Bit16u * amount, bool fcb = false);
bool DOS_WriteFile(Bit16u handle,Bit8u * data,Bit16u * amount,bool fcb = false);
bool DOS_SeekFile(Bit16u handle,Bit32u * pos,Bit32u type,bool fcb = false);
bool DOS_CloseFile(Bit16u handle,bool fcb = false);
bool DOS_FlushFile(Bit16u handle);
bool DOS_DuplicateEntry(Bit16u entry,Bit16u * newentry);
bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry);
bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate);
/* Routines for Drive Class */
bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry);
bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry,bool fcb = false);
bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status);
bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry);
bool DOS_CreateFile(char const * name,Bit16u attribute,Bit16u * entry, bool fcb = false);
bool DOS_UnlinkFile(char const * const name);
bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false);
bool DOS_FindNext(void);
@ -386,6 +386,7 @@ public:
void SetDiskBufferHeadPt(Bit32u _dbheadpt);
void SetStartOfUMBChain(Bit16u _umbstartseg);
void SetUMBChainState(Bit8u _umbchaining);
void SetBlockDevices(Bit8u _count);
Bit16u GetStartOfUMBChain(void);
Bit8u GetUMBChainState(void);
RealPt GetPointer(void);
@ -501,14 +502,16 @@ public:
void GetRecord(Bit16u & _cur_block,Bit8u & _cur_rec);
void SetRecord(Bit16u _cur_block,Bit8u _cur_rec);
void GetSeqData(Bit8u & _fhandle,Bit16u & _rec_size);
void SetSeqData(Bit8u _fhandle,Bit16u _rec_size);
void GetRandom(Bit32u & _random);
void SetRandom(Bit32u _random);
Bit8u GetDrive(void);
bool Extended(void);
void GetAttr(Bit8u & attr);
void SetAttr(Bit8u attr);
void SetResultAttr(Bit8u attr);
void SetResult(Bit32u size,Bit16u date,Bit16u time,Bit8u attr);
bool Valid(void);
void ClearBlockRecsize(void);
private:
bool extended;
PhysPt real_pt;
@ -528,6 +531,8 @@ private:
Bit8u sft_entries;
Bit8u share_attributes;
Bit8u extra_info;
/* Maybe swap file_handle and sft_entries now that fcbs
* aren't stored in the psp filetable anymore */
Bit8u file_handle;
Bit8u reserved[4];
/* end */
@ -622,6 +627,8 @@ struct DOS_Block {
bool verify;
bool breakcheck;
bool echo; // if set to true dev_con::read will echo input
bool direct_output;
bool internal_output;
struct {
RealPt mediaid;
RealPt tempdta;
@ -638,7 +645,7 @@ struct DOS_Block {
extern DOS_Block dos;
static Bit8u RealHandle(Bit16u handle) {
static INLINE Bit8u RealHandle(Bit16u handle) {
DOS_PSP psp(dos.psp());
return psp.GetFileHandle(handle);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -62,7 +62,7 @@ class DOS_DTA;
class DOS_File {
public:
DOS_File():flags(0) { name=0; refCtr = 0; hdrive=0xff; };
DOS_File():flags(0),time(0),date(0),attr(0),refCtr(0),open(false),name(0),hdrive(0xff) { };
DOS_File(const DOS_File& orig);
DOS_File & operator= (const DOS_File & orig);
virtual ~DOS_File(){if(name) delete [] name;};
@ -117,6 +117,23 @@ private:
Bitu devnum;
};
class localFile : public DOS_File {
public:
localFile(const char* name, FILE * handle);
bool Read(Bit8u * data,Bit16u * size);
bool Write(Bit8u * data,Bit16u * size);
bool Seek(Bit32u * pos,Bit32u type);
bool Close();
Bit16u GetInformation(void);
bool UpdateDateTimeFromHost(void);
void FlagReadOnlyMedium(void);
void Flush(void);
FILE * fhandle; //todo handle this properly
private:
bool read_only_medium;
enum { NONE,READ,WRITE } last_action;
};
/* The following variable can be lowered to free up some memory.
* The negative side effect: The stored searches will be turned over faster.
* Should not have impact on systems with few directory entries. */
@ -145,6 +162,8 @@ public:
void CacheOut (const char* path, bool ignoreLastDir = false);
void AddEntry (const char* path, bool checkExist = false);
void AddEntryDirOverlay (const char* path, bool checkExist = false);
void DeleteEntry (const char* path, bool ignoreLastDir = false);
void EmptyCache (void);
@ -155,7 +174,7 @@ public:
public:
CFileInfo(void) {
orgname[0] = shortname[0] = 0;
isDir = false;
isOverlayDir = isDir = false;
id = MAX_OPENDIRS;
nextEntry = shortNr = 0;
}
@ -166,6 +185,7 @@ public:
};
char orgname [CROSS_LEN];
char shortname [DOS_NAMELENGTH_ASCII];
bool isOverlayDir;
bool isDir;
Bit16u id;
Bitu nextEntry;
@ -189,7 +209,7 @@ private:
CFileInfo* FindDirInfo (const char* path, char* expandedPath);
bool RemoveSpaces (char* str);
bool OpenDir (CFileInfo* dir, const char* path, Bit16u& id);
void CreateEntry (CFileInfo* dir, const char* name, bool query_directory);
void CreateEntry (CFileInfo* dir, const char* name, bool is_directory);
void CopyEntry (CFileInfo* dir, CFileInfo* from);
Bit16u GetFreeID (CFileInfo* dir);
void Clear (void);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,14 +11,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_FPU_H
#define DOSBOX_FPU_H
#ifndef DOSBOX_DOSBOX_H
//So the right config.h gets included for C_DEBUG
#include "dosbox.h"
#endif
#ifndef DOSBOX_MEM_H
#include "mem.h"
#endif
@ -86,7 +91,7 @@ typedef struct {
FPU_Tag tags[9];
Bit16u cw,cw_mask_all;
Bit16u sw;
Bitu top;
Bit32u top;
FPU_Round round;
} FPU_rec;
@ -150,5 +155,22 @@ static INLINE void FPU_SET_C3(Bitu C){
if(C) fpu.sw |= 0x4000;
}
#define DB_FPU_STACK_CHECK_NONE 0
#define DB_FPU_STACK_CHECK_LOG 1
#define DB_FPU_STACK_CHECK_EXIT 2
//NONE is 0.74 behavior: not care about stack overflow/underflow
//Overflow is always logged/exited on.
//Underflow can be controlled with by this.
//LOG is giving a message when encountered
//EXIT is to hard exit.
//Currently pop is ignored in release mode and overflow is exit.
//in debug mode: pop will log and overflow is exit.
#if C_DEBUG
#define DB_FPU_STACK_CHECK_POP DB_FPU_STACK_CHECK_LOG
#define DB_FPU_STACK_CHECK_PUSH DB_FPU_STACK_CHECK_EXIT
#else
#define DB_FPU_STACK_CHECK_POP DB_FPU_STACK_CHECK_NONE
#define DB_FPU_STACK_CHECK_PUSH DB_FPU_STACK_CHECK_EXIT
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -24,7 +24,7 @@
class Section;
enum OPL_Mode {
OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3
OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3,OPL_opl3gold
};
#define CAPTURE_WAVE 0x01
#define CAPTURE_OPL 0x02

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_IPXSERVER_H_

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_JOYSTICK_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_KEYBOARD_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_LOGGING_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
/*
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_MAPPER_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_MEM_H

67
include/midi.h Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_MIDI_H
#define DOSBOX_MIDI_H
#ifndef DOSBOX_DOSBOX_H
#include "dosbox.h"
#endif
#ifndef DOSBOX_PROGRAMS_H
#include "programs.h"
#endif
class MidiHandler {
public:
MidiHandler();
virtual bool Open(const char * /*conf*/) {
LOG_MSG("No working midi device found/selected! Please check your settings and/or compilation environment.");
return true;
};
virtual void Close(void) {};
virtual void PlayMsg(Bit8u * /*msg*/) {};
virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {};
virtual const char * GetName(void) { return "none"; };
virtual void ListAll(Program * base) {};
virtual ~MidiHandler() { };
MidiHandler * next;
};
#define SYSEX_SIZE 8192
struct DB_Midi {
Bitu status;
Bitu cmd_len;
Bitu cmd_pos;
Bit8u cmd_buf[8];
Bit8u rt_buf[8];
struct {
Bit8u buf[SYSEX_SIZE];
Bitu used;
Bitu delay;
Bit32u start;
} sysex;
bool available;
MidiHandler * handler;
};
extern DB_Midi midi;
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -72,18 +72,27 @@ public:
void AddSamples_s16u_nonnative(Bitu len, const Bit16u * data);
void AddSamples_m32_nonnative(Bitu len, const Bit32s * data);
void AddSamples_s32_nonnative(Bitu len, const Bit32s * data);
void AddStretched(Bitu len,Bit16s * data); //Strech block up into needed data
void FillUp(void);
void Enable(bool _yesno);
MIXER_Handler handler;
float volmain[2];
float scale;
Bit32s volmul[2];
Bitu freq_add,freq_index;
Bitu done,needed;
Bits last[2];
//This gets added the frequency counter each mixer step
Bitu freq_add;
//When this flows over a new sample needs to be read from the device
Bitu freq_counter;
//Timing on how many samples have been done and were needed by th emixer
Bitu done, needed;
//Previous and next samples
Bits prevSample[2];
Bits nextSample[2];
const char * name;
bool interpolate;
bool enabled;
MixerChannel * next;
};

View File

@ -1,180 +0,0 @@
/* Standard data types used */
typedef unsigned char Bit8u;
typedef signed char Bit8s;
typedef unsigned short Bit16u;
typedef signed short Bit16s;
typedef unsigned long Bit32u;
typedef signed long Bit32s;
#if defined(_MSC_VER)
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
typedef unsigned long long int Bit64u;
typedef signed long long int Bit64s;
#endif
/* Setting up pointers to all subfunctions */
#ifdef MODULE_WANT_IO_READ
typedef Bit8u (* IO_ReadHandler)(Bit32u port);
static void (* IO_RegisterReadHandler)(Bit32u port,IO_ReadHandler handler,char * name);
static void (* IO_FreeReadHandler)(Bit32u port);
#endif
#ifdef MODULE_WANT_IO_WRITE
typedef void (* IO_WriteHandler)(Bit32u port,Bit8u value);
static void (* IO_RegisterWriteHandler)(Bit32u port,IO_WriteHandler handler,char * name);
static void (* IO_FreeWriteHandler)(Bit32u port);
#endif
#ifdef MODULE_WANT_IRQ_EOI
typedef void (* IRQ_EOIHandler)(void);
static void (* IRQ_RegisterEOIHandler)(Bit32u irq,IRQ_EOIHandler handler,char * name);
static void (* IRQ_FreeEOIHandler)(Bit32u irq);
#endif
#ifdef MODULE_WANT_IRQ
static void (* IRQ_Activate)(Bit32u irq);
static void (* IRQ_Deactivate)(Bit32u irq);
#endif
#ifdef MODULE_WANT_TIMER
typedef void (* TIMER_MicroHandler)(void);
static void (* TIMER_RegisterMicroHandler)(TIMER_MicroHandler handler,Bit32u micro);
#endif
#ifdef MODULE_WANT_TIMER_TICK
typedef void (* TIMER_TickHandler)(Bit32u ticks);
static void (* TIMER_RegisterTickHandler)(TIMER_TickHandler handler);
#endif
/*
4 8-bit and 4 16-bit channels you can read data from
16-bit reads are word sized
*/
#ifdef MODULE_WANT_DMA_READ
static void (* DMA_8_Read)(Bit32u chan,Bit8u * data,Bit16u size);
static void (* DMA_16_Read)(Bit32u chan,Bit8u * data,Bit16u size);
#endif
/*
4 8-bit and 4 16-bit channels you can write data from
16-bit writes are word sized
*/
#ifdef MODULE_WANT_DMA_READ
static void (* DMA_8_Write)(Bit32u chan,Bit8u * data,Bit16u size);
static void (* DMA_16_Write)(Bit32u chan,Bit8u * data,Bit16u size);
#endif
#ifdef MODULE_WANT_MIXER
/* The len here means the amount of samples needed not the buffersize it needed to fill */
typedef void (* MIXER_MixHandler)(Bit8u * sampdate,Bit32u len);
/* Different types if modes a mixer channel can work in */
#define MIXER_8MONO 0
#define MIXER_8STEREO 1
#define MIXER_16MONO 2
#define MIXER_16STEREO 3
struct MIXER_Channel;
#define MAX_AUDIO ((1<<(16-1))-1)
#define MIN_AUDIO -(1<<(16-1))
MIXER_Channel *(* MIXER_AddChannel)(MIXER_MixHandler handler,Bit32u freq,char * name);
void (* MIXER_SetVolume)(MIXER_Channel * chan,Bit8u vol);
void (* MIXER_SetFreq)(MIXER_Channel * chan,Bit32u freq);
void (* MIXER_SetMode)(MIXER_Channel * chan,Bit8u mode);
void (* MIXER_Enable)(MIXER_Channel * chan,bool enable);
#endif
typedef bool (* MODULE_FindHandler)(char * name,void * * function);
typedef char *(* MODULE_StartHandler)(MODULE_FindHandler find_handler);
#define MODULE_START_PROC "ModuleStart"
#ifdef MODULE_START_FUNCTION
#include <stdio.h>
#define GET_FUNCTION(a) \
if (!find_handler(#a ,(void * *) &a)) { \
return "Can't find requested function"; \
};
#if defined (WIN32)
#include <windows.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
extern "C" {
__declspec(dllexport)
#endif
char * ModuleStart (MODULE_FindHandler find_handler) {
#ifdef MODULE_WANT_IRQ_EOI
GET_FUNCTION(IRQ_RegisterEOIHandler);
GET_FUNCTION(IRQ_FreeEOIHandler);
#endif
#ifdef MODULE_WANT_IRQ
GET_FUNCTION(IRQ_Activate);
GET_FUNCTION(IRQ_Deactivate);
#endif
#ifdef MODULE_WANT_IO_READ
GET_FUNCTION(IO_RegisterReadHandler);
GET_FUNCTION(IO_FreeReadHandler);
#endif
#ifdef MODULE_WANT_IO_WRITE
GET_FUNCTION(IO_RegisterWriteHandler);
GET_FUNCTION(IO_FreeWriteHandler);
#endif
#ifdef MODULE_WANT_TIMER
GET_FUNCTION(TIMER_RegisterMicroHandler);
#endif
#ifdef MODULE_WANT_TIMER_TICKS
GET_FUNCTION(TIMER_RegisterTickHandler);
#endif
#ifdef MODULE_WANT_DMA_READ
GET_FUNCTION(DMA_8_Read);
GET_FUNCTION(DMA_16_Read);
#endif
#ifdef MODULE_WANT_DMA_WRITE
GET_FUNCTION(DMA_8_Write);
GET_FUNCTION(DMA_16_Write);
#endif
#ifdef MODULE_WANT_MIXER
GET_FUNCTION(MIXER_AddChannel);
GET_FUNCTION(MIXER_SetVolume);
GET_FUNCTION(MIXER_SetFreq);
GET_FUNCTION(MIXER_SetMode);
GET_FUNCTION(MIXER_Enable);
#endif
return MODULE_START_FUNCTION;
}
#if defined (WIN32)
}
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -36,6 +36,7 @@ void Mouse_ButtonPressed(Bit8u button);
void Mouse_ButtonReleased(Bit8u button);
void Mouse_AutoLock(bool enable);
void Mouse_NewVideoMode(void);
void Mouse_BeforeNewVideoMode(bool setmode);
void Mouse_AfterNewVideoMode(bool setmode);
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -50,9 +50,11 @@ class PageDirectory;
#define PFLAG_READABLE 0x1
#define PFLAG_WRITEABLE 0x2
#define PFLAG_HASROM 0x4
#define PFLAG_HASCODE 0x8 //Page contains dynamic code
#define PFLAG_HASCODE32 0x8 //Page contains 32-bit dynamic code
#define PFLAG_NOCODE 0x10 //No dynamic code can be generated here
#define PFLAG_INIT 0x20 //No dynamic code can be generated here
#define PFLAG_HASCODE16 0x40 //Page contains 16-bit dynamic code
#define PFLAG_HASCODE (PFLAG_HASCODE32|PFLAG_HASCODE16)
#define LINK_START ((1024+64)/4) //Start right after the HMA
@ -226,7 +228,7 @@ void PAGING_InitTLBBank(tlb_entry **bank);
static INLINE tlb_entry *get_tlb_entry(PhysPt address) {
Bitu index=(address>>12);
if (TLB_BANKS && (index > TLB_SIZE)) {
if (TLB_BANKS && (index >= TLB_SIZE)) {
Bitu bank=(address>>BANK_SHIFT) - 1;
if (!paging.tlbh_banks[bank])
PAGING_InitTLBBank(&paging.tlbh_banks[bank]);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_PCI_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_PIC_H
@ -29,11 +29,7 @@ typedef void (PIC_EOIHandler) (void);
typedef void (* PIC_EventHandler)(Bitu val);
#define PIC_MAXIRQ 15
#define PIC_NOIRQ 0xFF
extern Bitu PIC_IRQCheck;
extern Bitu PIC_IRQActive;
extern Bitu PIC_Ticks;
static INLINE float PIC_TickIndex(void) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_REGS_H
@ -59,7 +59,7 @@ struct Segment {
enum SegNames { es=0,cs,ss,ds,fs,gs};
struct Segments {
Bitu val[8];
Bit16u val[8];
PhysPt phys[8];
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_RENDER_H
@ -58,8 +58,8 @@ typedef struct {
float fps;
} src;
struct {
Bitu count;
Bitu max;
int count;
int max;
Bitu index;
Bit8u hadSkip[RENDER_SKIP_CACHE];
} frameskip;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -46,7 +46,7 @@
#ifndef CH_CSTDIO
#define CH_CSTDIO
#include <cstdio>
#include <stdio.h>
#endif
@ -58,7 +58,6 @@ public:
Hex():_hex(0) { };
bool operator==(Hex const& other) {return _hex == other._hex;}
operator int () const { return _hex; }
};
class Value {
@ -78,40 +77,40 @@ private:
public:
class WrongType { }; // Conversion error class
enum Etype { V_NONE, V_HEX, V_BOOL, V_INT, V_STRING, V_DOUBLE,V_CURRENT} type;
/* Constructors */
Value() :_string(0), type(V_NONE) { };
Value(Hex in) :_hex(in), type(V_HEX) { };
Value(int in) :_int(in), type(V_INT) { };
Value(bool in) :_bool(in), type(V_BOOL) { };
Value(double in) :_double(in), type(V_DOUBLE) { };
Value(std::string const& in) :_string(new std::string(in)),type(V_STRING) { };
Value(char const * const in) :_string(new std::string(in)),type(V_STRING) { };
Value() :_hex(0), _bool(false),_int(0), _string(0), _double(0), type(V_NONE) { };
Value(Hex in) :_hex(in),_bool(false),_int(0), _string(0), _double(0), type(V_HEX) { };
Value(int in) :_hex(0), _bool(false),_int(in),_string(0), _double(0), type(V_INT) { };
Value(bool in) :_hex(0), _bool(in) ,_int(0), _string(0), _double(0), type(V_BOOL) { };
Value(double in) :_hex(0), _bool(false),_int(0), _string(0), _double(in),type(V_DOUBLE) { };
Value(std::string const& in) :_hex(0), _bool(false),_int(0), _string(new std::string(in)),_double(0), type(V_STRING) { };
Value(char const * const in) :_hex(0), _bool(false),_int(0), _string(new std::string(in)),_double(0), type(V_STRING) { };
Value(Value const& in):_string(0) {plaincopy(in);}
~Value() { destroy();};
Value(std::string const& in,Etype _t) :_string(0),type(V_NONE) {SetValue(in,_t);}
Value(std::string const& in,Etype _t) :_hex(0),_bool(false),_int(0),_string(0),_double(0),type(V_NONE) {SetValue(in,_t);}
/* Assigment operators */
Value& operator= (Hex in) throw(WrongType) { return copy(Value(in));}
Value& operator= (int in) throw(WrongType) { return copy(Value(in));}
Value& operator= (bool in) throw(WrongType) { return copy(Value(in));}
Value& operator= (double in) throw(WrongType) { return copy(Value(in));}
Value& operator= (std::string const& in) throw(WrongType) { return copy(Value(in));}
Value& operator= (char const * const in) throw(WrongType) { return copy(Value(in));}
Value& operator= (Value const& in) throw(WrongType) { return copy(Value(in));}
Value& operator= (Hex in) { return copy(Value(in));}
Value& operator= (int in) { return copy(Value(in));}
Value& operator= (bool in) { return copy(Value(in));}
Value& operator= (double in) { return copy(Value(in));}
Value& operator= (std::string const& in) { return copy(Value(in));}
Value& operator= (char const * const in) { return copy(Value(in));}
Value& operator= (Value const& in) { return copy(Value(in));}
bool operator== (Value const & other);
operator bool () const throw(WrongType);
operator Hex () const throw(WrongType);
operator int () const throw(WrongType);
operator double () const throw(WrongType);
operator char const* () const throw(WrongType);
bool SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType);
operator bool () const;
operator Hex () const;
operator int () const;
operator double () const;
operator char const* () const;
bool SetValue(std::string const& in,Etype _type = V_CURRENT);
std::string ToString() const;
private:
void destroy() throw();
Value& copy(Value const& in) throw(WrongType);
Value& copy(Value const& in);
void plaincopy(Value const& in) throw();
bool set_hex(std::string const& in);
bool set_int(std::string const&in);
@ -132,19 +131,26 @@ public:
virtual bool SetValue(std::string const& str)=0;
Value const& GetValue() const { return value;}
Value const& Get_Default_Value() const { return default_value; }
//CheckValue returns true if value is in suggested_values;
//CheckValue returns true, if value is in suggested_values;
//Type specific properties are encouraged to override this and check for type
//specific features.
virtual bool CheckValue(Value const& in, bool warn);
//Set interval value to in or default if in is invalid. force always sets the value.
bool SetVal(Value const& in, bool forced,bool warn=true) {
if(forced || CheckValue(in,warn)) {value = in; return true;} else { value = default_value; return false;}}
virtual ~Property(){ }
public:
virtual ~Property(){ }
virtual const std::vector<Value>& GetValues() const;
Value::Etype Get_type(){return default_value.type;}
Changeable::Value getChange() {return change;}
protected:
//Set interval value to in or default if in is invalid. force always sets the value.
//Can be overriden to set a different value if invalid.
virtual bool SetVal(Value const& in, bool forced,bool warn=true) {
if(forced || CheckValue(in,warn)) {
value = in; return true;
} else {
value = default_value; return false;
}
}
Value value;
std::vector<Value> suggested_values;
typedef std::vector<Value>::iterator iter;
@ -155,12 +161,12 @@ protected:
class Prop_int:public Property {
public:
Prop_int(std::string const& _propname,Changeable::Value when, int _value)
:Property(_propname,when) {
:Property(_propname,when) {
default_value = value = _value;
min = max = -1;
}
Prop_int(std::string const& _propname,Changeable::Value when, int _min,int _max,int _value)
:Property(_propname,when) {
:Property(_propname,when) {
default_value = value = _value;
min = _min;
max = _max;
@ -171,6 +177,9 @@ public:
bool SetValue(std::string const& in);
~Prop_int(){ }
virtual bool CheckValue(Value const& in, bool warn);
// Override SetVal, so it takes min,max in account when there are no suggested values
virtual bool SetVal(Value const& in, bool forced,bool warn=true);
private:
Value min,max;
};
@ -188,7 +197,7 @@ public:
class Prop_bool:public Property {
public:
Prop_bool(std::string const& _propname, Changeable::Value when, bool _value)
:Property(_propname,when) {
:Property(_propname,when) {
default_value = value = _value;
}
bool SetValue(std::string const& in);
@ -198,7 +207,7 @@ public:
class Prop_string:public Property{
public:
Prop_string(std::string const& _propname, Changeable::Value when, char const * const _value)
:Property(_propname,when) {
:Property(_propname,when) {
default_value = value = _value;
}
bool SetValue(std::string const& in);
@ -209,7 +218,7 @@ class Prop_path:public Prop_string{
public:
std::string realpath;
Prop_path(std::string const& _propname, Changeable::Value when, char const * const _value)
:Prop_string(_propname,when,_value) {
:Prop_string(_propname,when,_value) {
default_value = value = _value;
realpath = _value;
}
@ -220,7 +229,7 @@ public:
class Prop_hex:public Property {
public:
Prop_hex(std::string const& _propname, Changeable::Value when, Hex _value)
:Property(_propname,when) {
:Property(_propname,when) {
default_value = value = _value;
}
bool SetValue(std::string const& in);
@ -274,7 +283,7 @@ public:
Prop_path* Add_path(std::string const& _propname, Property::Changeable::Value when, char const * const _value=NULL);
Prop_bool* Add_bool(std::string const& _propname, Property::Changeable::Value when, bool _value=false);
Prop_hex* Add_hex(std::string const& _propname, Property::Changeable::Value when, Hex _value=0);
// void Add_double(char const * const _propname, double _value=0.0);
// void Add_double(char const * const _propname, double _value=0.0);
Prop_multival *Add_multi(std::string const& _propname, Property::Changeable::Value when,std::string const& sep);
Prop_multival_remain *Add_multiremain(std::string const& _propname, Property::Changeable::Value when,std::string const& sep);
@ -297,10 +306,10 @@ public:
class Prop_multival:public Property{
protected:
Section_prop* section;
std::string seperator;
std::string separator;
void make_default_value();
public:
Prop_multival(std::string const& _propname, Changeable::Value when,std::string const& sep):Property(_propname,when), section(new Section_prop("")),seperator(sep) {
Prop_multival(std::string const& _propname, Changeable::Value when,std::string const& sep):Property(_propname,when), section(new Section_prop("")),separator(sep) {
default_value = value = "";
}
Section_prop *GetSection() { return section; }
@ -317,7 +326,7 @@ public:
virtual bool SetValue(std::string const& input);
};
class Section_line: public Section{
public:
Section_line(std::string const& _sectionname):Section(_sectionname){}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -35,11 +35,12 @@
#define CMD_MAXCMDS 20
#define CMD_OLDSIZE 4096
extern Bitu call_shellstop;
class DOS_Shell;
/* first_shell is used to add and delete stuff from the shell env
* by "external" programs. (config) */
extern Program * first_shell;
extern DOS_Shell * first_shell;
class DOS_Shell;
class BatchFile {
public:

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -53,6 +53,7 @@ bool IsHexWord(char * word);
Bits ConvDecWord(char * word);
Bits ConvHexWord(char * word);
void trim(std::string& str);
void upcase(std::string &str);
void lowcase(std::string &str);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef DOSBOX_TIMER_H

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
/*
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -112,7 +112,7 @@ typedef struct {
typedef enum {
PART,
LINE,
DRAWLINE,
EGALINE
} Drawmode;
@ -427,6 +427,10 @@ void VGA_DAC_CombineColor(Bit8u attr,Bit8u pal);
void VGA_DAC_SetEntry(Bitu entry,Bit8u red,Bit8u green,Bit8u blue);
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val);
typedef enum {CGA, EGA, MONO} EGAMonitorMode;
void VGA_ATTR_SetEGAMonitorPalette(EGAMonitorMode m);
/* The VGA Subfunction startups */
void VGA_SetupAttr(void);
void VGA_SetupMemory(Section* sec);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -2,7 +2,7 @@
!define VER_MINOR 74
!define APP_NAME "DOSBox ${VER_MAYOR}.${VER_MINOR} Installer"
!define COMP_NAME "DOSBox Team"
!define COPYRIGHT "Copyright © 2002-2011 DOSBox Team"
!define COPYRIGHT "Copyright © 2002-2019 DOSBox Team"
!define DESCRIPTION "DOSBox Installer"
VIProductVersion "${VER_MAYOR}.${VER_MINOR}.0.0"

View File

@ -13,7 +13,8 @@ endif
dosbox_SOURCES = dosbox.cpp $(ico_stuff)
dosbox_LDADD = cpu/libcpu.a debug/libdebug.a dos/libdos.a fpu/libfpu.a hardware/libhardware.a gui/libgui.a \
ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a libs/gui_tk/libgui_tk.a
ints/libints.a misc/libmisc.a shell/libshell.a hardware/mame/libmame.a \
hardware/serialport/libserial.a libs/gui_tk/libgui_tk.a
EXTRA_DIST = winres.rc dosbox.ico

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -33,7 +33,7 @@
CallBack_Handler CallBack_Handlers[CB_MAX];
char* CallBack_Description[CB_MAX];
static Bitu call_stop,call_idle,call_default,call_default2;
static Bitu call_stop,call_idle,call_default;
Bitu call_priv_io;
static Bitu illegal_handler(void) {
@ -173,6 +173,26 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction
phys_writew(physAddress+0x01,(Bit16u)0x0008);
return (use_cb?7:3);
case CB_RETF_STI:
phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI
if (use_cb) {
phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x01,(Bit8u)0xCB); //A RETF Instruction
return (use_cb?6:2);
case CB_RETF_CLI:
phys_writeb(physAddress+0x00,(Bit8u)0xFA); //CLI
if (use_cb) {
phys_writeb(physAddress+0x01,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x02,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x03,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x01,(Bit8u)0xCB); //A RETF Instruction
return (use_cb?6:2);
case CB_IRET:
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
@ -256,7 +276,15 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writew(physAddress+0x0b,(Bit16u)0x20e6); // out 0x20, al
phys_writeb(physAddress+0x0d,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x0e,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x15:0x0f);
phys_writeb(physAddress+0x0f,(Bit8u)0xfa); // cli
phys_writew(physAddress+0x10,(Bit16u)0x20b0); // mov al, 0x20
phys_writew(physAddress+0x12,(Bit16u)0x20e6); // out 0x20, al
phys_writeb(physAddress+0x14,(Bit8u)0x55); // push bp
phys_writew(physAddress+0x15,(Bit16u)0x05cd); // int 5
phys_writeb(physAddress+0x17,(Bit8u)0x5d); // pop bp
phys_writeb(physAddress+0x18,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x19,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x20:0x1a);
case CB_IRQ9: // pic cascade interrupt
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
@ -274,26 +302,32 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
return (use_cb?0x0e:0x0a);
case CB_IRQ12: // ps2 mouse int74
if (!use_cb) E_Exit("int74 callback must implement a callback handler!");
phys_writeb(physAddress+0x00,(Bit8u)0x1e); // push ds
phys_writeb(physAddress+0x01,(Bit8u)0x06); // push es
phys_writew(physAddress+0x02,(Bit16u)0x6066); // pushad
phys_writeb(physAddress+0x04,(Bit8u)0xfc); // cld
phys_writeb(physAddress+0x05,(Bit8u)0xfb); // sti
phys_writeb(physAddress+0x06,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x07,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x08,(Bit16u)callback); //The immediate word
return 0x0a;
phys_writeb(physAddress+0x00,(Bit8u)0xfb); // sti
phys_writeb(physAddress+0x01,(Bit8u)0x1e); // push ds
phys_writeb(physAddress+0x02,(Bit8u)0x06); // push es
phys_writew(physAddress+0x03,(Bit16u)0x6066); // pushad
phys_writeb(physAddress+0x05,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x06,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x07,(Bit16u)callback); //The immediate word
phys_writeb(physAddress+0x09,(Bit8u)0x50); // push ax
phys_writew(physAddress+0x0a,(Bit16u)0x20b0); // mov al, 0x20
phys_writew(physAddress+0x0c,(Bit16u)0xa0e6); // out 0xa0, al
phys_writew(physAddress+0x0e,(Bit16u)0x20e6); // out 0x20, al
phys_writeb(physAddress+0x10,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x11,(Bit8u)0xfc); // cld
phys_writeb(physAddress+0x12,(Bit8u)0xCB); //A RETF Instruction
return 0x13;
case CB_IRQ12_RET: // ps2 mouse int74 return
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writeb(physAddress+0x00,(Bit8u)0xfa); // cli
phys_writew(physAddress+0x01,(Bit16u)0x20b0); // mov al, 0x20
phys_writew(physAddress+0x03,(Bit16u)0xa0e6); // out 0xa0, al
phys_writew(physAddress+0x05,(Bit16u)0x20e6); // out 0x20, al
if (use_cb) {
phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writew(physAddress+0x07,(Bit16u)0x6166); // popad
phys_writeb(physAddress+0x09,(Bit8u)0x07); // pop es
phys_writeb(physAddress+0x0a,(Bit8u)0x1f); // pop ds
@ -304,22 +338,26 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writew(physAddress+0x01,(Bit16u)0x60e4); // in al, 0x60
phys_writew(physAddress+0x03,(Bit16u)0xe03c); // cmp al, 0xe0
if (use_cb) {
phys_writew(physAddress+0x05,(Bit16u)0x0674); // je skip
phys_writew(physAddress+0x05,(Bit16u)0x0b74); // je skip
phys_writeb(physAddress+0x07,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x08,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x09,(Bit16u)callback); //The immediate word
physAddress+=4;
} else {
phys_writew(physAddress+0x05,(Bit16u)0x0274); // je skip
phys_writew(physAddress+0x05,(Bit16u)0x0774); // je skip
}
phys_writew(physAddress+0x07,(Bit16u)0x09cd); // int 9
phys_writeb(physAddress+0x07,(Bit8u)0x1e); // push ds
phys_writew(physAddress+0x08,(Bit16u)0x406a); // push 0x0040
phys_writeb(physAddress+0x0a,(Bit8u)0x1f); // pop ds
phys_writew(physAddress+0x0b,(Bit16u)0x09cd); // int 9
phys_writeb(physAddress+0x0d,(Bit8u)0x1f); // pop ds
// jump here to (skip):
phys_writeb(physAddress+0x09,(Bit8u)0xfa); // cli
phys_writew(physAddress+0x0a,(Bit16u)0x20b0); // mov al, 0x20
phys_writew(physAddress+0x0c,(Bit16u)0x20e6); // out 0x20, al
phys_writeb(physAddress+0x0e,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x0f,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x14:0x10);
phys_writeb(physAddress+0x0e,(Bit8u)0xfa); // cli
phys_writew(physAddress+0x0f,(Bit16u)0x20b0); // mov al, 0x20
phys_writew(physAddress+0x11,(Bit16u)0x20e6); // out 0x20, al
phys_writeb(physAddress+0x13,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x14,(Bit8u)0xcf); //An IRET Instruction
return (use_cb?0x19:0x15);
case CB_MOUSE:
phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd
physAddress+=9;
@ -446,8 +484,51 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_
phys_writew(physAddress+0x02,(Bit16u)0x0ECD); // int 0e
phys_writeb(physAddress+0x04,(Bit8u)0xCF); //An IRET Instruction
return (use_cb?9:5);
case CB_VESA_WAIT:
if (use_cb) E_Exit("VESA wait must not implement a callback handler!");
phys_writeb(physAddress+0x00,(Bit8u)0xFB); // sti
phys_writeb(physAddress+0x01,(Bit8u)0x50); // push ax
phys_writeb(physAddress+0x02,(Bit8u)0x52); // push dx
phys_writeb(physAddress+0x03,(Bit8u)0xBA); // mov dx,
phys_writew(physAddress+0x04,(Bit16u)0x03DA); // 0x3da
phys_writeb(physAddress+0x06,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x07,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x09,(Bit16u)0xFB75); // jne $-5
phys_writeb(physAddress+0x0B,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x0C,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x0E,(Bit16u)0xFB74); // je $-5
phys_writeb(physAddress+0x10,(Bit8u)0x5A); // pop dx
phys_writeb(physAddress+0x11,(Bit8u)0x58); // pop ax
phys_writeb(physAddress+0x12,(Bit8u)0xCB); //A RETF Instruction
return 19;
case CB_VESA_PM:
if (use_cb) {
phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4
phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction
phys_writew(physAddress+0x02,(Bit16u)callback); //The immediate word
physAddress+=4;
}
phys_writew(physAddress+0x00,(Bit16u)0xC3F6); // test bl,
phys_writeb(physAddress+0x02,(Bit8u)0x80); // 0x80
phys_writew(physAddress+0x03,(Bit16u)0x1674); // je $+22
phys_writew(physAddress+0x05,(Bit16u)0x5066); // push ax
phys_writew(physAddress+0x07,(Bit16u)0x5266); // push dx
phys_writew(physAddress+0x09,(Bit16u)0xBA66); // mov dx,
phys_writew(physAddress+0x0B,(Bit16u)0x03DA); // 0x3da
phys_writeb(physAddress+0x0D,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x0E,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x10,(Bit16u)0xFB75); // jne $-5
phys_writeb(physAddress+0x12,(Bit8u)0xEC); // in al,dx
phys_writew(physAddress+0x13,(Bit16u)0x08A8); // test al,8
phys_writew(physAddress+0x15,(Bit16u)0xFB74); // je $-5
phys_writew(physAddress+0x17,(Bit16u)0x5A66); // pop dx
phys_writew(physAddress+0x19,(Bit16u)0x5866); // pop ax
if (use_cb)
phys_writeb(physAddress+0x1B,(Bit8u)0xC3); //A RETN Instruction
return (use_cb?32:27);
default:
E_Exit("CALLBACK:Setup:Illegal type %d",type);
E_Exit("CALLBACK:Setup:Illegal type %" sBitfs(u),type);
//E_Exit("CALLBACK:Setup:Illegal type %d",type);
}
return 0;
}
@ -563,8 +644,6 @@ void CALLBACK_Init(Section* /*sec*/) {
/* Default handlers for unhandled interrupts that have to be non-null */
call_default=CALLBACK_Allocate();
CALLBACK_Setup(call_default,&default_handler,CB_IRET,"default");
call_default2=CALLBACK_Allocate();
CALLBACK_Setup(call_default2,&default_handler,CB_IRET,"default");
/* Only setup default handler for first part of interrupt table */
for (Bit16u ct=0;ct<0x60;ct++) {
@ -585,10 +664,9 @@ void CALLBACK_Init(Section* /*sec*/) {
}
// setup a few interrupt handlers that point to bios IRETs by default
real_writed(0,0x0e*4,CALLBACK_RealPointer(call_default2)); //design your own railroad
real_writed(0,0x66*4,CALLBACK_RealPointer(call_default)); //war2d
real_writed(0,0x67*4,CALLBACK_RealPointer(call_default));
real_writed(0,0x68*4,CALLBACK_RealPointer(call_default));
if (machine==MCH_CGA) real_writed(0,0x68*4,0); //Popcorn
real_writed(0,0x5c*4,CALLBACK_RealPointer(call_default)); //Network stuff
//real_writed(0,0xf*4,0); some games don't like it

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -65,6 +65,7 @@
#if C_FPU
#define CPU_FPU 1 //Enable FPU escape instructions
#define X86_DYNFPU_DH_ENABLED
#endif
enum {
@ -154,12 +155,10 @@ static DynReg DynRegs[G_MAX];
#define DREG(_WHICH_) &DynRegs[G_ ## _WHICH_ ]
static struct {
Bitu ea,tmpb,tmpd,stack,shift,newesp;
Bit32u ea,tmpb,tmpd,stack,shift,newesp;
} extra_regs;
static void IllegalOption(const char* msg) {
E_Exit("DynCore: illegal option in %s",msg);
}
#define IllegalOption(msg) E_Exit("DYNX86: illegal option in " msg)
#include "core_dyn_x86/cache.h"
@ -168,17 +167,37 @@ static struct {
Bit32u readdata;
} core_dyn;
static struct {
Bit32u state[32];
#if defined(X86_DYNFPU_DH_ENABLED)
static struct dyn_dh_fpu {
Bit16u cw,host_cw;
bool state_used;
// some fields expanded here for alignment purposes
struct {
Bit32u cw;
Bit32u sw;
Bit32u tag;
Bit32u ip;
Bit32u cs;
Bit32u ea;
Bit32u ds;
Bit8u st_reg[8][10];
} state;
FPU_P_Reg temp,temp2;
Bit32u dh_fpu_enabled;
Bit32u state_used;
Bit32u cw,host_cw;
Bit8u temp_state[128];
} dyn_dh_fpu;
#endif
#define X86 0x01
#define X86_64 0x02
#if C_TARGETCPU == X86_64
#include "core_dyn_x86/risc_x64.h"
#elif C_TARGETCPU == X86
#include "core_dyn_x86/risc_x86.h"
#else
#error DYN_X86 core not supported for this CPU target.
#endif
struct DynState {
DynReg regs[G_MAX];
@ -233,44 +252,33 @@ static void dyn_restoreregister(DynReg * src_reg, DynReg * dst_reg) {
#include "core_dyn_x86/decoder.h"
#if defined (_MSC_VER)
#define DH_FPU_SAVE_REINIT \
{ \
__asm { \
__asm fnsave dyn_dh_fpu.state[0] \
} \
dyn_dh_fpu.state_used=false; \
dyn_dh_fpu.state[0]|=0x3f; \
}
#else
#define DH_FPU_SAVE_REINIT \
{ \
__asm__ volatile ( \
"fnsave %0 \n" \
: "=m" (dyn_dh_fpu.state[0]) \
: \
: "memory" \
); \
dyn_dh_fpu.state_used=false; \
dyn_dh_fpu.state[0]|=0x3f; \
}
#endif
Bits CPU_Core_Dyn_X86_Run(void) {
// helper class to auto-save DH_FPU state on function exit
class auto_dh_fpu {
public:
~auto_dh_fpu(void) {
#if defined(X86_DYNFPU_DH_ENABLED)
if (dyn_dh_fpu.state_used)
gen_dh_fpu_save();
#endif
};
};
auto_dh_fpu fpu_saver;
/* Determine the linear address of CS:EIP */
restart_core:
PhysPt ip_point=SegPhys(cs)+reg_eip;
#if C_HEAVY_DEBUG
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#endif
#endif
CodePageHandler * chandler=0;
if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
CPU_Exception(cpu.exception.which,cpu.exception.error);
goto restart_core;
}
if (!chandler) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CPU_Core_Normal_Run();
}
/* Find correct Dynamic Block to run */
@ -279,10 +287,11 @@ restart_core:
if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
block=CreateCacheBlock(chandler,ip_point,32);
} else {
Bitu old_cycles=CPU_Cycles;
Bit32s old_cycles=CPU_Cycles;
CPU_Cycles=1;
// manually save
fpu_saver = auto_dh_fpu();
Bits nc_retcode=CPU_Core_Normal_Run();
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
if (!nc_retcode) {
CPU_Cycles=old_cycles-1;
goto restart_core;
@ -294,41 +303,42 @@ restart_core:
run_block:
cache.block.running=0;
BlockReturn ret=gen_runcode(block->cache.start);
#if C_DEBUG
cycle_count += 32;
#endif
switch (ret) {
case BR_Iret:
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return debugCallback;
}
#endif
#endif
if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) {
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CBRET_NONE;
}
goto restart_core;
}
cpudecoder=CPU_Core_Dyn_X86_Trap_Run;
if (!dyn_dh_fpu.state_used) return CBRET_NONE;
DH_FPU_SAVE_REINIT
return CBRET_NONE;
case BR_Normal:
/* Maybe check if we staying in the same page? */
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#endif
goto restart_core;
case BR_Cycles:
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
if (!dyn_dh_fpu.state_used) return CBRET_NONE;
DH_FPU_SAVE_REINIT
#endif
return CBRET_NONE;
case BR_CallBack:
if (!dyn_dh_fpu.state_used) return core_dyn.callback;
DH_FPU_SAVE_REINIT
return core_dyn.callback;
case BR_SMCBlock:
// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip);
@ -337,21 +347,19 @@ run_block:
case BR_Opcode:
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=1;
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CPU_Core_Normal_Run();
#if (C_DEBUG)
case BR_OpcodeFull:
CPU_CycleLeft+=CPU_Cycles;
CPU_Cycles=1;
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CPU_Core_Full_Run();
#endif
case BR_Link1:
case BR_Link2:
{
Bitu temp_ip=SegPhys(cs)+reg_eip;
Bit32u temp_ip=SegPhys(cs)+reg_eip;
CodePageHandler * temp_handler=(CodePageHandler *)get_tlb_readhandler(temp_ip);
if (temp_handler->flags & PFLAG_HASCODE) {
if (temp_handler->flags & (cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16)) {
block=temp_handler->FindCacheBlock(temp_ip & 4095);
if (!block) goto restart_core;
cache.block.running->LinkTo(ret==BR_Link2,block);
@ -360,12 +368,11 @@ run_block:
}
goto restart_core;
}
if (dyn_dh_fpu.state_used) DH_FPU_SAVE_REINIT
return CBRET_NONE;
}
Bits CPU_Core_Dyn_X86_Trap_Run(void) {
Bits oldCycles = CPU_Cycles;
Bit32s oldCycles = CPU_Cycles;
CPU_Cycles = 1;
cpu.trap_skip = false;
@ -438,25 +445,15 @@ void CPU_Core_Dyn_X86_Init(void) {
/* Init the generator */
gen_init();
#if defined(X86_DYNFPU_DH_ENABLED)
/* Init the fpu state */
dyn_dh_fpu.dh_fpu_enabled=true;
dyn_dh_fpu.state_used=false;
dyn_dh_fpu.cw=0x37f;
#if defined (_MSC_VER)
__asm {
__asm finit
__asm fsave dyn_dh_fpu.state[0]
__asm fstcw dyn_dh_fpu.host_cw
}
#else
__asm__ volatile (
"finit \n"
"fsave %0 \n"
"fstcw %1 \n"
: "=m" (dyn_dh_fpu.state[0]), "=m" (dyn_dh_fpu.host_cw)
:
: "memory"
);
// FINIT
memset(&dyn_dh_fpu.state, 0, sizeof(dyn_dh_fpu.state));
dyn_dh_fpu.state.cw = 0x37F;
dyn_dh_fpu.state.tag = 0xFFFF;
#endif
return;
@ -471,62 +468,10 @@ void CPU_Core_Dyn_X86_Cache_Close(void) {
cache_close();
}
void CPU_Core_Dyn_X86_Cache_Reset(void) {
cache_reset();
}
void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu) {
#if defined(X86_DYNFPU_DH_ENABLED)
dyn_dh_fpu.dh_fpu_enabled=dh_fpu;
}
Bit32u fpu_state[32];
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm fsave fpu_state[0]
__asm finit
}
#else
__asm__ volatile (
"fsave %0 \n"
"finit \n"
: "=m" (fpu_state[0])
:
: "memory"
);
#endif
}
}
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
if (dyn_dh_fpu.dh_fpu_enabled) {
if (dyn_dh_fpu.state_used!=0) {
#if defined (_MSC_VER)
__asm {
__asm frstor fpu_state[0]
}
#else
__asm__ volatile (
"frstor %0 \n"
:
: "m" (fpu_state[0])
:
);
#endif
}
}
}
#else
void CPU_Core_Dyn_X86_SaveDHFPUState(void) {
}
void CPU_Core_Dyn_X86_RestoreDHFPUState(void) {
}
#endif

View File

@ -1,2 +1,2 @@
noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h string.h \
dyn_fpu.h dyn_fpu_dh.h
noinst_HEADERS = cache.h helpers.h decoder.h risc_x86.h risc_x64.h string.h \
dyn_fpu.h dyn_fpu_dh.h

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -73,7 +73,7 @@ public:
void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) {
phys_page=_phys_page;
old_pagehandler=_old_pagehandler;
flags=old_pagehandler->flags|PFLAG_HASCODE;
flags=old_pagehandler->flags|(cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16);
flags&=~PFLAG_WRITEABLE;
active_blocks=0;
active_count=16;
@ -466,6 +466,10 @@ static INLINE void cache_addd(Bit32u val) {
cache.pos+=4;
}
static INLINE void cache_addq(Bit64u val) {
*(Bit64u*)cache.pos=val;
cache.pos+=8;
}
static void gen_return(BlockReturn retcode);
@ -510,14 +514,14 @@ static void cache_init(bool enable) {
#endif
if(!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
cache_code=(Bit8u*)(((int)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //Bitu is same size as a pointer.
cache_code_link_blocks=cache_code;
cache_code+=PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting excute permission on the code cache has failed!");
LOG_MSG("Setting execute permission on the code cache has failed!");
#endif
CacheBlock * block=cache_getblock();
cache.block.first=block;
@ -569,75 +573,3 @@ static void cache_close(void) {
cache_code_link_blocks = NULL;
cache_initialized = false; */
}
static void cache_reset(void) {
if (cache_initialized) {
for (;;) {
if (cache.used_pages) {
CodePageHandler * cpage=cache.used_pages;
CodePageHandler * npage=cache.used_pages->next;
cpage->ClearRelease();
delete cpage;
cache.used_pages=npage;
} else break;
}
if (cache_blocks == NULL) {
cache_blocks=(CacheBlock*)malloc(CACHE_BLOCKS*sizeof(CacheBlock));
if(!cache_blocks) E_Exit("Allocating cache_blocks has failed");
}
memset(cache_blocks,0,sizeof(CacheBlock)*CACHE_BLOCKS);
cache.block.free=&cache_blocks[0];
for (Bits i=0;i<CACHE_BLOCKS-1;i++) {
cache_blocks[i].link[0].to=(CacheBlock *)1;
cache_blocks[i].link[1].to=(CacheBlock *)1;
cache_blocks[i].cache.next=&cache_blocks[i+1];
}
if (cache_code_start_ptr==NULL) {
#if defined (WIN32)
cache_code_start_ptr=(Bit8u*)VirtualAlloc(0,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP,
MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (!cache_code_start_ptr)
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#else
cache_code_start_ptr=(Bit8u*)malloc(CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP-1+PAGESIZE_TEMP);
#endif
if (!cache_code_start_ptr) E_Exit("Allocating dynamic core cache memory failed");
cache_code=(Bit8u*)(((int)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
cache_code_link_blocks=cache_code;
cache_code+=PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting excute permission on the code cache has failed!");
#endif
}
CacheBlock * block=cache_getblock();
cache.block.first=block;
cache.block.active=block;
block->cache.start=&cache_code[0];
block->cache.size=CACHE_TOTAL;
block->cache.next=0; //Last block in the list
/* Setup the default blocks for block linkage returns */
cache.pos=&cache_code_link_blocks[0];
link_blocks[0].cache.start=cache.pos;
gen_return(BR_Link1);
cache.pos=&cache_code_link_blocks[32];
link_blocks[1].cache.start=cache.pos;
gen_return(BR_Link2);
cache.free_pages=0;
cache.last_page=0;
cache.used_pages=0;
/* Setup the code pages */
for (Bitu i=0;i<CACHE_PAGES;i++) {
CodePageHandler * newpage=new CodePageHandler();
newpage->next=cache.free_pages;
cache.free_pages=newpage;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,13 +11,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define X86_DYNFPU_DH_ENABLED
#define X86_INLINED_MEMACCESS
@ -53,19 +52,26 @@ static struct DynDecode {
static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) {
Bit8u rdval;
const Bitu cflag = cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16;
//Ensure page contains memory:
if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true;
PageHandler * handler=get_tlb_readhandler(lin_addr);
if (handler->flags & PFLAG_HASCODE) {
cph=( CodePageHandler *)handler;
return false;
if (handler->flags & cflag) return false;
cph->ClearRelease();
cph=0;
handler=get_tlb_readhandler(lin_addr);
}
if (handler->flags & PFLAG_NOCODE) {
if (PAGING_ForcePageInit(lin_addr)) {
handler=get_tlb_readhandler(lin_addr);
if (handler->flags & PFLAG_HASCODE) {
cph=( CodePageHandler *)handler;
return false;
if (handler->flags & cflag) return false;
cph->ClearRelease();
cph=0;
handler=get_tlb_readhandler(lin_addr);
}
}
if (handler->flags & PFLAG_NOCODE) {
@ -325,7 +331,7 @@ static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub,Bit32u dflags
}
static void dyn_check_bool_exception(DynReg * check) {
gen_dop_byte(DOP_OR,check,0,check,0);
gen_dop_byte(DOP_TEST,check,0,check,0);
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
dyn_savestate(&save_info[used_save_info].state);
if (!decode.cycles) decode.cycles++;
@ -337,7 +343,7 @@ static void dyn_check_bool_exception(DynReg * check) {
}
static void dyn_check_bool_exception_al(void) {
cache_addw(0xc00a); // or al, al
cache_addw(0xC084); // test al,al
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
dyn_savestate(&save_info[used_save_info].state);
if (!decode.cycles) decode.cycles++;
@ -352,7 +358,7 @@ static void dyn_check_bool_exception_al(void) {
static void dyn_check_irqrequest(void) {
gen_load_host(&PIC_IRQCheck,DREG(TMPB),4);
gen_dop_word(DOP_OR,true,DREG(TMPB),DREG(TMPB));
gen_dop_word(DOP_TEST,true,DREG(TMPB),DREG(TMPB));
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_NZ);
gen_releasereg(DREG(TMPB));
dyn_savestate(&save_info[used_save_info].state);
@ -396,21 +402,29 @@ static void dyn_fill_blocks(void) {
dyn_save_critical_regs();
gen_return(BR_Cycles);
break;
#ifdef X86_DYNFPU_DH_ENABLED
case fpu_restore:
dyn_loadstate(&save_info[sct].state);
gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4);
gen_sop_word(SOP_INC,true,DREG(TMPB));
GenReg * gr1=FindDynReg(DREG(TMPB));
#if C_TARGETCPU == X86
cache_addb(0xd9); // FNSTCW fpu.host_cw
cache_addb(0x3d);
cache_addd((Bit32u)(&dyn_dh_fpu.host_cw));
cache_addb(0xdd); // FRSTOR fpu.state (fpu_restore)
cache_addb(0x25);
cache_addd((Bit32u)(&(dyn_dh_fpu.state[0])));
cache_addb(0x89); // mov fpu.state_used,1
cache_addb(0x05|(gr1->index<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.state_used)));
gen_releasereg(DREG(TMPB));
cache_addd((Bit32u)(&dyn_dh_fpu.state));
cache_addb(0xC6); // mov byte [fpu.state_used], 1
cache_addb(0x05);
cache_addd((Bit32u)(&dyn_dh_fpu.state_used));
cache_addb(1);
#else // X86_64
opcode(7).setabsaddr(&dyn_dh_fpu.host_cw).Emit8(0xD9); // FNSTCW [&fpu.host_cw]
opcode(4).setabsaddr(&dyn_dh_fpu.state).Emit8(0xDD); // FRSTOR [&fpu.state]
opcode(0).setimm(1,1).setabsaddr(&dyn_dh_fpu.state_used).Emit8(0xC6); // mov byte[], imm8
#endif
dyn_synchstate(&save_info[sct].state);
gen_create_jump(save_info[sct].return_pos);
break;
#endif
}
}
used_save_info=0;
@ -418,13 +432,13 @@ static void dyn_fill_blocks(void) {
#if !defined(X86_INLINED_MEMACCESS)
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high) {
gen_protectflags();
gen_call_function((void *)&mem_readb_checked,"%Dd%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readb_checked,"%Dd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,1,high);
gen_mov_host(&core_dyn.readdata,dst,1,high?4:0);
}
static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
gen_protectflags();
if (high) gen_call_function((void *)&mem_writeb_checked,"%Dd%Dh",addr,val);
else gen_call_function((void *)&mem_writeb_checked,"%Dd%Dd",addr,val);
@ -432,8 +446,8 @@ static void dyn_write_byte(DynReg * addr,DynReg * val,Bitu high) {
}
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Id",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
if (dword) gen_call_function((void *)&mem_readd_checked,"%Dd%Ip",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Dd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
}
@ -443,33 +457,34 @@ static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
else gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
dyn_check_bool_exception_al();
}
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
gen_protectflags();
gen_call_function((void *)&mem_readb_checked,"%Ddr%Id",addr,&core_dyn.readdata);
gen_call_function((void *)&mem_readb_checked,"%Drd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,1,high);
gen_mov_host(&core_dyn.readdata,dst,1,high?4:0);
}
static void dyn_write_byte_release(DynReg * addr,DynReg * val,Bitu high) {
static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
gen_protectflags();
if (high) gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dh",addr,val);
else gen_call_function((void *)&mem_writeb_checked,"%Ddr%Dd",addr,val);
if (high) gen_call_function((void *)&mem_writeb_checked,"%Drd%Dh",addr,val);
else gen_call_function((void *)&mem_writeb_checked,"%Drd%Dd",addr,val);
dyn_check_bool_exception_al();
}
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_readd_checked,"%Ddr%Id",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
if (dword) gen_call_function((void *)&mem_readd_checked,"%Drd%Ip",addr,&core_dyn.readdata);
else gen_call_function((void *)&mem_readw_checked,"%Drd%Ip",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,dword?4:2);
}
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
gen_protectflags();
if (dword) gen_call_function((void *)&mem_writed_checked,"%Ddr%Dd",addr,val);
else gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
if (dword) gen_call_function((void *)&mem_writed_checked,"%Drd%Dd",addr,val);
else gen_call_function((void *)&mem_writew_checked,"%Drd%Dd",addr,val);
dyn_check_bool_exception_al();
}
#else
#if C_TARGETCPU == X86
static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
gen_protectflags();
@ -495,12 +510,12 @@ static void dyn_read_intro(DynReg * addr,bool release_addr=true) {
cache_addw(0xc18b); // mov eax,ecx
}
bool mem_readb_checked_dcx86(PhysPt address) {
static bool mem_readb_checked_dcx86(PhysPt address) {
return get_tlb_readhandler(address)->readb_checked(address, (Bit8u*)(&core_dyn.readdata));
}
static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
dyn_read_intro(addr,false);
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high,bool release=false) {
dyn_read_intro(addr,release);
cache_addw(0xe8c1); // shr eax,0x0c
cache_addb(0x0c);
@ -537,45 +552,7 @@ static void dyn_read_byte(DynReg * addr,DynReg * dst,Bitu high) {
dst->flags|=DYNFLG_CHANGED;
}
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,Bitu high) {
dyn_read_intro(addr);
cache_addw(0xe8c1); // shr eax,0x0c
cache_addb(0x0c);
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
cache_addb(0x85);
cache_addd((Bit32u)(&paging.tlb.read[0]));
cache_addw(0xc085); // test eax,eax
Bit8u* je_loc=gen_create_branch(BR_Z);
cache_addw(0x048a); // mov al,[eax+ecx]
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(je_loc);
cache_addb(0x51); // push ecx
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_readb_checked_dcx86) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,4
cache_addb(0x04);
cache_addw(0x012c); // sub al,1
dyn_check_bool_exception_ne();
cache_addw(0x058a); //mov al,[]
cache_addd((Bit32u)(&core_dyn.readdata));
gen_fill_jump(jmp_loc);
x86gen.regs[X86_REG_EAX]->notusable=true;
GenReg * genreg=FindDynReg(dst);
x86gen.regs[X86_REG_EAX]->notusable=false;
cache_addw(0xc08a+(genreg->index<<11)+(high?0x2000:0));
dst->flags|=DYNFLG_CHANGED;
}
bool mem_readd_checked_dcx86(PhysPt address) {
static bool mem_readd_checked_dcx86(PhysPt address) {
if ((address & 0xfff)<0xffd) {
HostPt tlb_addr=get_tlb_read(address);
if (tlb_addr) {
@ -587,96 +564,70 @@ bool mem_readd_checked_dcx86(PhysPt address) {
} else return mem_unalignedreadd_checked(address, &core_dyn.readdata);
}
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword) {
if (dword) {
dyn_read_intro(addr,false);
cache_addw(0xe8d1); // shr eax,0x1
Bit8u* jb_loc1=gen_create_branch(BR_B);
cache_addw(0xe8d1); // shr eax,0x1
Bit8u* jb_loc2=gen_create_branch(BR_B);
cache_addw(0xe8c1); // shr eax,0x0a
cache_addb(0x0a);
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
cache_addb(0x85);
cache_addd((Bit32u)(&paging.tlb.read[0]));
cache_addw(0xc085); // test eax,eax
Bit8u* je_loc=gen_create_branch(BR_Z);
GenReg * genreg=FindDynReg(dst,true);
cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx]
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(jb_loc2);
gen_fill_branch(je_loc);
cache_addb(0x51); // push ecx
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,4
cache_addb(0x04);
cache_addw(0x012c); // sub al,1
dyn_check_bool_exception_ne();
gen_mov_host(&core_dyn.readdata,dst,4);
dst->flags|=DYNFLG_CHANGED;
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_readw_checked,"%Dd%Id",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,2);
}
static bool mem_readw_checked_dcx86(PhysPt address) {
if ((address & 0xfff)<0xfff) {
HostPt tlb_addr=get_tlb_read(address);
if (tlb_addr) {
*(Bit16u*)&core_dyn.readdata=host_readw(tlb_addr+address);
return false;
} else {
return get_tlb_readhandler(address)->readw_checked(address, (Bit16u*)&core_dyn.readdata);
}
} else return mem_unalignedreadw_checked(address, (Bit16u*)&core_dyn.readdata);
}
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
if (dword) {
dyn_read_intro(addr);
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword,bool release=false) {
dyn_read_intro(addr,release);
cache_addw(0xe8d1); // shr eax,0x1
Bit8u* jb_loc1=gen_create_branch(BR_B);
cache_addw(0xe8d1); // shr eax,0x1
Bit8u* jb_loc2=gen_create_branch(BR_B);
cache_addw(0xe8c1); // shr eax,0x0a
cache_addb(0x0a);
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
cache_addb(0x85);
cache_addd((Bit32u)(&paging.tlb.read[0]));
cache_addw(0xc085); // test eax,eax
Bit8u* je_loc=gen_create_branch(BR_Z);
GenReg * genreg=FindDynReg(dst,true);
cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx]
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(jb_loc2);
gen_fill_branch(je_loc);
cache_addb(0x51); // push ecx
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,4
cache_addb(0x04);
cache_addw(0x012c); // sub al,1
dyn_check_bool_exception_ne();
gen_mov_host(&core_dyn.readdata,dst,4);
dst->flags|=DYNFLG_CHANGED;
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_readw_checked,"%Ddr%Id",addr,&core_dyn.readdata);
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dst,2);
if (!dword) {
x86gen.regs[X86_REG_EAX]->notusable=true;
x86gen.regs[X86_REG_ECX]->notusable=true;
}
GenReg * genreg=FindDynReg(dst,dword);
if (!dword) {
x86gen.regs[X86_REG_EAX]->notusable=false;
x86gen.regs[X86_REG_ECX]->notusable=false;
}
cache_addw(0xc8c1); // ror eax, 12
cache_addb(0x0c);
cache_addb(0x3d); // cmp eax, 0xFFD00000/0xFFF00000
cache_addd(dword ? 0xffd00000:0xfff00000);
Bit8u* jb_loc1=gen_create_branch(BR_NB);
cache_addb(0x25); // and eax, 0x000FFFFF
cache_addd(0x000fffff);
cache_addw(0x048b); // mov eax,paging.tlb.read[eax*TYPE Bit32u]
cache_addb(0x85);
cache_addd((Bit32u)(&paging.tlb.read[0]));
cache_addw(0xc085); // test eax,eax
Bit8u* je_loc=gen_create_branch(BR_Z);
if (!dword) cache_addb(0x66);
cache_addw(0x048b+(genreg->index <<(8+3))); // mov dest,[eax+ecx]
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(je_loc);
if (!dword) {
cache_addw(0x0589+(genreg->index<<11)); // mov [core_dyn.readdata], dst
cache_addd((Bit32u)&core_dyn.readdata);
}
cache_addb(0x51); // push ecx
cache_addb(0xe8);
if (dword) cache_addd(((Bit32u)&mem_readd_checked_dcx86) - (Bit32u)cache.pos-4);
else cache_addd(((Bit32u)&mem_readw_checked_dcx86) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,4
cache_addb(0x04);
cache_addw(0x012c); // sub al,1
dyn_check_bool_exception_ne();
gen_mov_host(&core_dyn.readdata,dst,4);
dst->flags|=DYNFLG_CHANGED;
gen_fill_jump(jmp_loc);
}
static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
@ -710,52 +661,13 @@ static void dyn_write_intro(DynReg * addr,bool release_addr=true) {
cache_addw(0xc88b); // mov ecx,eax
}
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high) {
dyn_write_intro(addr,false);
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high,bool release=false) {
dyn_write_intro(addr,release);
GenReg * genreg=FindDynReg(val);
cache_addw(0xe9c1); // shr ecx,0x0c
cache_addb(0x0c);
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
cache_addb(0x8d);
cache_addd((Bit32u)(&paging.tlb.write[0]));
cache_addw(0xc985); // test ecx,ecx
Bit8u* je_loc=gen_create_branch(BR_Z);
cache_addw(0x0488+(genreg->index<<11)+(high?0x2000:0)); // mov [eax+ecx],reg
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(je_loc);
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
cache_addb(0x52); // push edx
cache_addb(0x50+genreg->index);
cache_addb(0x50); // push eax
if (GCC_UNLIKELY(high)) cache_addw(0xe086+((genreg->index+(genreg->index<<3))<<8));
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_writeb_checked) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,8
cache_addb(0x08);
cache_addw(0x012c); // sub al,1
cache_addb(0x5a); // pop edx
// Restore registers to be used again
x86gen.regs[X86_REG_EAX]->notusable=false;
x86gen.regs[X86_REG_ECX]->notusable=false;
dyn_check_bool_exception_ne();
gen_fill_jump(jmp_loc);
}
static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
dyn_write_intro(addr);
GenReg * genreg=FindDynReg(val);
cache_addw(0xe9c1); // shr ecx,0x0c
cache_addb(0x0c);
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
cache_addw(0x0c8b); // mov ecx,paging.tlb.write[ecx*TYPE Bit32u]
cache_addb(0x8d);
cache_addd((Bit32u)(&paging.tlb.write[0]));
cache_addw(0xc985); // test ecx,ecx
@ -788,104 +700,286 @@ static void dyn_write_byte_release(DynReg * addr,DynReg * val,bool high) {
gen_fill_jump(jmp_loc);
}
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword) {
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword,bool release=false) {
dyn_write_intro(addr,release);
GenReg * genreg=FindDynReg(val);
cache_addw(0xc9c1); // ror ecx, 12
cache_addb(0x0c);
cache_addw(0xf981); // cmp ecx, 0xFFD00000/0xFFF00000
cache_addd(dword ? 0xffd00000:0xfff00000);
Bit8u* jb_loc1=gen_create_branch(BR_NB);
cache_addw(0xe181); // and ecx, 0x000FFFFF
cache_addd(0x000fffff);
cache_addw(0x0c8b); // mov ecx,paging.tlb.write[ecx*TYPE Bit32u]
cache_addb(0x8d);
cache_addd((Bit32u)(&paging.tlb.write[0]));
cache_addw(0xc985); // test ecx,ecx
Bit8u* je_loc=gen_create_branch(BR_Z);
if (!dword) cache_addb(0x66);
cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(je_loc);
cache_addb(0x52); // push edx
cache_addb(0x50+genreg->index);
cache_addb(0x50); // push eax
cache_addb(0xe8);
if (dword) cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4);
else cache_addd(((Bit32u)&mem_writew_checked) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,8
cache_addb(0x08);
cache_addw(0x012c); // sub al,1
cache_addb(0x5a); // pop edx
// Restore registers to be used again
x86gen.regs[X86_REG_EAX]->notusable=false;
x86gen.regs[X86_REG_ECX]->notusable=false;
dyn_check_bool_exception_ne();
gen_fill_jump(jmp_loc);
}
#else // X86_64
static bool mem_readd_checked_dcx64(PhysPt address, Bit32u* dst) {
return get_tlb_readhandler(address)->readd_checked(address, dst);
}
static bool mem_readw_checked_dcx64(PhysPt address, Bit16u* dst) {
return get_tlb_readhandler(address)->readw_checked(address, dst);
}
static bool mem_writed_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writed_checked(address, val);
}
static bool mem_writew_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writew_checked(address, val);
}
static bool mem_readb_checked_dcx64(PhysPt address, Bit8u* dst) {
return get_tlb_readhandler(address)->readb_checked(address, dst);
}
static bool mem_writeb_checked_dcx64(PhysPt address, Bitu val) {
return get_tlb_writehandler(address)->writeb_checked(address, val);
}
static void dyn_read_word(DynReg * addr,DynReg * dst,bool dword,bool release=false) {
DynState callstate;
Bit8u tmp;
gen_protectflags();
GenReg *gensrc = FindDynReg(addr);
if (dword && release) gen_releasereg(addr);
GenReg *gendst = FindDynReg(dst,dword);
if (!dword && release) gen_releasereg(addr);
gensrc->notusable = true;
x64gen.regs[reg_args[0]]->notusable=true;
x64gen.regs[reg_args[1]]->notusable=true;
tmp = GetNextReg();
gensrc->notusable = false;
x64gen.regs[reg_args[0]]->notusable=false;
x64gen.regs[reg_args[1]]->notusable=false;
dyn_savestate(&callstate);
Bit8u *page_brk;
opcode(tmp).set64().setea(gensrc->index,-1,0,dword?3:1).Emit8(0x8D); // lea tmp, [dst+(dword?3:1)]
if (dword) {
dyn_write_intro(addr,false);
GenReg * genreg=FindDynReg(val);
cache_addw(0xe9d1); // shr ecx,0x1
Bit8u* jb_loc1=gen_create_branch(BR_B);
cache_addw(0xe9d1); // shr ecx,0x1
Bit8u* jb_loc2=gen_create_branch(BR_B);
cache_addw(0xe9c1); // shr ecx,0x0a
cache_addb(0x0a);
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
cache_addb(0x8d);
cache_addd((Bit32u)(&paging.tlb.write[0]));
cache_addw(0xc985); // test ecx,ecx
Bit8u* je_loc=gen_create_branch(BR_Z);
cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(jb_loc2);
gen_fill_branch(je_loc);
cache_addb(0x52); // push edx
cache_addb(0x50+genreg->index);
cache_addb(0x50); // push eax
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,8
cache_addb(0x08);
cache_addw(0x012c); // sub al,1
cache_addb(0x5a); // pop edx
// Restore registers to be used again
x86gen.regs[X86_REG_EAX]->notusable=false;
x86gen.regs[X86_REG_ECX]->notusable=false;
dyn_check_bool_exception_ne();
gen_fill_jump(jmp_loc);
opcode(4).set64().setimm(~0xFFF,4).setrm(tmp).Emit8(0x81); // and tmp, ~0xFFF
opcode(gensrc->index).set64().setrm(tmp).Emit8(0x39); // cmp tmp,src
page_brk=gen_create_branch(BR_NBE);
} else {
gen_protectflags();
gen_call_function((void *)&mem_writew_checked,"%Dd%Dd",addr,val);
dyn_check_bool_exception_al();
opcode(0,false).setimm(0xFFF,2).setrm(tmp).Emit8(0xF7); // test tmpw,0xFFF
page_brk=gen_create_branch(BR_Z);
}
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
// mov tmp, [8*tmp+paging.tlb.read(rbp)]
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
Bit8u *nomap=gen_create_branch(BR_Z);
//mov dst, [tmp+src]
opcode(gendst->index,dword).setea(tmp,gensrc->index).Emit8(0x8B);
Bit8u* jmp_loc = gen_create_short_jump();
gen_fill_branch(page_brk);
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_unalignedreadd_checked:(void*)mem_unalignedreadw_checked));
Bit8u* page_jmp = gen_create_short_jump();
gen_fill_branch(nomap);
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_readd_checked_dcx64:(void*)mem_readw_checked_dcx64));
gen_fill_short_jump(page_jmp);
if (gensrc->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gensrc->index).Emit8(0x8B);
}
gendst->Clear();
x64gen.regs[reg_args[1]]->Clear();
gen_load_imm(ARG1_REG, (Bitu)dst->data);
gen_call_ptr(NULL, tmp);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
dst->flags |= DYNFLG_CHANGED;
gen_fill_short_jump(jmp_loc);
}
static void dyn_read_byte(DynReg * addr,DynReg * dst,bool high,bool release=false) {
DynState callstate;
Bit8u tmp;
gen_protectflags();
GenReg *gensrc = FindDynReg(addr);
GenReg *gendst = FindDynReg(dst);
tmp = GetNextReg(high);
if (release) gen_releasereg(addr);
dyn_savestate(&callstate);
if (gendst->index>3) IllegalOption("dyn_read_byte");
opcode(tmp).setrm(gensrc->index).Emit8(0x8B); // mov tmp, src
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmp,12
// mov tmp, [8*tmp+paging.tlb.read(rbp)]
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.read-(Bits)&cpu_regs).Emit8(0x8B);
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
Bit8u *nomap=gen_create_branch(BR_Z);
int src = gensrc->index;
if (high && src>=8) { // can't use REX prefix with high-byte reg
opcode(tmp).set64().setrm(src).Emit8(0x03); // add tmp, src
src = -1;
}
// mov dst, byte [tmp+src]
opcode(gendst->index,true,high?4:0).setea(tmp,src).Emit8(0x8A);
Bit8u* jmp_loc=gen_create_short_jump();
gen_fill_branch(nomap);
if (gensrc->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gensrc->index).Emit8(0x8B); // mov ARG0,src
}
x64gen.regs[reg_args[1]]->Clear();
gen_load_imm(ARG1_REG, (Bitu)(high?((Bit8u*)dst->data)+1:dst->data));
gendst->Clear();
gen_call_ptr((void*)mem_readb_checked_dcx64);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
dst->flags |= DYNFLG_CHANGED;
gen_fill_short_jump(jmp_loc);
}
static void dyn_write_word(DynReg * addr,DynReg * val,bool dword,bool release=false) {
DynState callstate;
Bit8u tmp;
gen_protectflags();
GenReg *gendst = FindDynReg(addr);
GenReg *genval = FindDynReg(val);
x64gen.regs[reg_args[0]]->notusable=true;
x64gen.regs[reg_args[1]]->notusable=true;
tmp = GetNextReg();
x64gen.regs[reg_args[0]]->notusable=false;
x64gen.regs[reg_args[1]]->notusable=false;
if (release) gen_releasereg(addr);
dyn_savestate(&callstate);
Bit8u *page_brk;
opcode(tmp).set64().setea(gendst->index,-1,0,dword?3:1).Emit8(0x8D); // lea tmp, [dst+(dword?3:1)]
if (dword) {
opcode(4).set64().setimm(~0xFFF,4).setrm(tmp).Emit8(0x81); // and tmp, ~0xFFF
opcode(gendst->index).set64().setrm(tmp).Emit8(0x39); // cmp tmp,dst
page_brk=gen_create_branch(BR_NBE);
} else {
opcode(0,false).setimm(0xFFF,2).setrm(tmp).Emit8(0xF7); // test tmpw,0xFFF
page_brk=gen_create_branch(BR_Z);
}
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
// mov tmp, [8*tmp+paging.tlb.write(rbp)]
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
Bit8u *nomap=gen_create_branch(BR_Z);
//mov [tmp+src], dst
opcode(genval->index,dword).setea(tmp,gendst->index).Emit8(0x89);
Bit8u* jmp_loc = gen_create_short_jump();
gen_fill_branch(page_brk);
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_unalignedwrited_checked:(void*)mem_unalignedwritew_checked));
Bit8u* page_jmp = gen_create_short_jump();
gen_fill_branch(nomap);
gen_load_imm(tmp, (Bitu)(dword?(void*)mem_writed_checked_dcx64:(void*)mem_writew_checked_dcx64));
gen_fill_short_jump(page_jmp);
if (gendst->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gendst->index).Emit8(0x8B);
}
gen_load_arg_reg(1, val, dword ? "d":"w");
gen_call_ptr(NULL, tmp);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
gen_fill_short_jump(jmp_loc);
}
static void dyn_write_byte(DynReg * addr,DynReg * val,bool high,bool release=false) {
DynState callstate;
Bit8u tmp;
gen_protectflags();
GenReg *gendst = FindDynReg(addr);
GenReg *genval = FindDynReg(val);
tmp = GetNextReg(high);
if (release) gen_releasereg(addr);
dyn_savestate(&callstate);
if (genval->index>3) IllegalOption("dyn_write_byte");
opcode(tmp).setrm(gendst->index).Emit8(0x8B); // mov tmpd, dst
opcode(5).setrm(tmp).setimm(12,1).Emit8(0xC1); // shr tmpd,12
// mov tmp, [8*tmp+paging.tlb.write(rbp)]
opcode(tmp).set64().setea(5,tmp,3,(Bits)paging.tlb.write-(Bits)&cpu_regs).Emit8(0x8B);
opcode(tmp).set64().setrm(tmp).Emit8(0x85); // test tmp,tmp
Bit8u *nomap=gen_create_branch(BR_Z);
int dst = gendst->index;
if (high && dst>=8) { // can't use REX prefix with high-byte reg
opcode(tmp).set64().setrm(dst).Emit8(0x03); // add tmp, dst
dst = -1;
}
// mov byte [tmp+src], val
opcode(genval->index,true,high?4:0).setea(tmp,dst).Emit8(0x88);
Bit8u* jmp_loc=gen_create_short_jump();
gen_fill_branch(nomap);
if (gendst->index != ARG0_REG) {
x64gen.regs[reg_args[0]]->Clear();
opcode(ARG0_REG).setrm(gendst->index).Emit8(0x8B); // mov ARG0,dst
}
gen_load_arg_reg(1, val, high ? "h":"l");
gen_call_ptr((void*)mem_writeb_checked_dcx64);
dyn_check_bool_exception_al();
dyn_synchstate(&callstate);
gen_fill_short_jump(jmp_loc);
}
#endif
static void dyn_read_word_release(DynReg * addr,DynReg * dst,bool dword) {
dyn_read_word(addr,dst,dword,addr!=dst);
}
static void dyn_read_byte_release(DynReg * addr,DynReg * dst,bool high) {
dyn_read_byte(addr,dst,high,addr!=dst);
}
static void dyn_write_word_release(DynReg * addr,DynReg * val,bool dword) {
if (dword) {
dyn_write_intro(addr);
GenReg * genreg=FindDynReg(val);
cache_addw(0xe9d1); // shr ecx,0x1
Bit8u* jb_loc1=gen_create_branch(BR_B);
cache_addw(0xe9d1); // shr ecx,0x1
Bit8u* jb_loc2=gen_create_branch(BR_B);
cache_addw(0xe9c1); // shr ecx,0x0a
cache_addb(0x0a);
cache_addw(0x0c8b); // mov ecx,paging.tlb.read[ecx*TYPE Bit32u]
cache_addb(0x8d);
cache_addd((Bit32u)(&paging.tlb.write[0]));
cache_addw(0xc985); // test ecx,ecx
Bit8u* je_loc=gen_create_branch(BR_Z);
cache_addw(0x0489+(genreg->index <<(8+3))); // mov [eax+ecx],reg
cache_addb(0x08);
Bit8u* jmp_loc=gen_create_jump();
gen_fill_branch(jb_loc1);
gen_fill_branch(jb_loc2);
gen_fill_branch(je_loc);
cache_addb(0x52); // push edx
cache_addb(0x50+genreg->index);
cache_addb(0x50); // push eax
cache_addb(0xe8);
cache_addd(((Bit32u)&mem_writed_checked) - (Bit32u)cache.pos-4);
cache_addw(0xc483); // add esp,8
cache_addb(0x08);
cache_addw(0x012c); // sub al,1
cache_addb(0x5a); // pop edx
// Restore registers to be used again
x86gen.regs[X86_REG_EAX]->notusable=false;
x86gen.regs[X86_REG_ECX]->notusable=false;
dyn_check_bool_exception_ne();
gen_fill_jump(jmp_loc);
} else {
gen_protectflags();
gen_call_function((void *)&mem_writew_checked,"%Ddr%Dd",addr,val);
dyn_check_bool_exception_al();
}
dyn_write_word(addr,val,dword,true);
}
static void dyn_write_byte_release(DynReg * addr,DynReg * src,bool high) {
dyn_write_byte(addr,src,high,true);
}
#endif
@ -931,9 +1025,9 @@ static void dyn_pop(DynReg * dynreg,bool checked=true) {
gen_dop_word(DOP_ADD,true,DREG(STACK),DREG(SS));
if (checked) {
if (decode.big_op) {
gen_call_function((void *)&mem_readd_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
gen_call_function((void *)&mem_readd_checked,"%Drd%Ip",DREG(STACK),&core_dyn.readdata);
} else {
gen_call_function((void *)&mem_readw_checked,"%Drd%Id",DREG(STACK),&core_dyn.readdata);
gen_call_function((void *)&mem_readw_checked,"%Drd%Ip",DREG(STACK),&core_dyn.readdata);
}
dyn_check_bool_exception_al();
gen_mov_host(&core_dyn.readdata,dynreg,decode.big_op?4:2);
@ -1048,7 +1142,7 @@ skip_extend_word:
segbase=DREG(DS);
Bitu val;
if (decode_fetchd_imm(val)) {
gen_mov_host((void*)val,DREG(EA),4);
gen_dop_word_imm_mem(DOP_MOV,true,DREG(EA),(void*)val);
if (!addseg) {
gen_lea(reg_ea,DREG(EA),scaled,scale,0);
} else {
@ -1081,7 +1175,7 @@ skip_extend_word:
case 2: {
Bitu val;
if (decode_fetchd_imm(val)) {
gen_mov_host((void*)val,DREG(EA),4);
gen_dop_word_imm_mem(DOP_MOV,true,DREG(EA),(void*)val);
if (!addseg) {
gen_lea(DREG(EA),DREG(EA),scaled,scale,0);
gen_lea(reg_ea,DREG(EA),base,0,0);
@ -1212,7 +1306,7 @@ static void dyn_mov_ebgb(void) {
DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
if (decode.modrm.mod<3) {
dyn_fill_ea();
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4);
dyn_write_byte_release(DREG(EA),rm_reg,rm_regi!=0);
} else {
gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi);
}
@ -1223,7 +1317,7 @@ static void dyn_mov_gbeb(void) {
DynReg * rm_reg=&DynRegs[decode.modrm.reg&3];Bitu rm_regi=decode.modrm.reg&4;
if (decode.modrm.mod<3) {
dyn_fill_ea();
dyn_read_byte_release(DREG(EA),rm_reg,rm_regi);
dyn_read_byte_release(DREG(EA),rm_reg,rm_regi!=0);
} else {
gen_dop_byte(DOP_MOV,rm_reg,rm_regi,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
}
@ -1553,7 +1647,7 @@ static void dyn_grp2_ev(grp2_types type) {
if (decode_fetchb_imm(val)) {
if (decode.modrm.reg < 4) gen_needflags();
else gen_discardflags();
gen_load_host((void*)val,DREG(TMPB),1);
gen_dop_byte_imm_mem(DOP_MOV,DREG(TMPB),0,(void*)val);
gen_shift_word_cl(decode.modrm.reg,decode.big_op,src,DREG(TMPB));
gen_releasereg(DREG(TMPB));
break;
@ -1612,7 +1706,7 @@ static void dyn_grp3_eb(void) {
gen_dop_byte(DOP_MOV,DREG(TMPB),0,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4);
gen_releasereg(DREG(EAX));
gen_call_function((decode.modrm.reg==6) ? (void *)&dyn_helper_divb : (void *)&dyn_helper_idivb,
"%Rd%Dd",DREG(TMPB),DREG(TMPB));
"%Rd%Drd",DREG(TMPB),DREG(TMPB));
dyn_check_bool_exception(DREG(TMPB));
goto skipsave;
}
@ -1654,7 +1748,7 @@ static void dyn_grp3_ev(void) {
void * func=(decode.modrm.reg==6) ?
(decode.big_op ? (void *)&dyn_helper_divd : (void *)&dyn_helper_divw) :
(decode.big_op ? (void *)&dyn_helper_idivd : (void *)&dyn_helper_idivw);
gen_call_function(func,"%Rd%Dd",DREG(TMPB),DREG(TMPW));
gen_call_function(func,"%Rd%Drd",DREG(TMPB),DREG(TMPW));
dyn_check_bool_exception(DREG(TMPB));
gen_releasereg(DREG(TMPB));
goto skipsave;
@ -1732,8 +1826,8 @@ static void dyn_pop_ev(void) {
if (decode.modrm.mod<3) {
dyn_fill_ea();
// dyn_write_word_release(DREG(EA),DREG(TMPW),decode.big_op);
if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
else gen_call_function((void *)&mem_writew_inline,"%Ddr%Dd",DREG(EA),DREG(TMPW));
if (decode.big_op) gen_call_function((void *)&mem_writed_inline,"%Drd%Dd",DREG(EA),DREG(TMPW));
else gen_call_function((void *)&mem_writew_inline,"%Drd%Dd",DREG(EA),DREG(TMPW));
} else {
gen_dop_word(DOP_MOV,decode.big_op,&DynRegs[decode.modrm.rm],DREG(TMPW));
}
@ -1854,7 +1948,7 @@ static void dyn_loop(LoopTypes type) {
branch2=gen_create_branch(BR_Z);
break;
case LOOP_JCXZ:
gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
gen_dop_word(DOP_TEST,decode.big_addr,DREG(ECX),DREG(ECX));
gen_releasereg(DREG(ECX));
branch2=gen_create_branch(BR_NZ);
break;
@ -1975,8 +2069,8 @@ static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) {
#define dh_fpu_startup() { \
fpu_used=true; \
gen_protectflags(); \
gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),4); \
gen_dop_word_imm(DOP_CMP,true,DREG(TMPB),0); \
gen_load_host(&dyn_dh_fpu.state_used,DREG(TMPB),1); \
gen_dop_byte(DOP_TEST,DREG(TMPB),0,DREG(TMPB),0); \
gen_releasereg(DREG(TMPB)); \
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_Z); \
dyn_savestate(&save_info[used_save_info].state); \
@ -2002,15 +2096,15 @@ static CacheBlock * CreateCacheBlock(CodePageHandler * codepage,PhysPt start,Bit
decode.block->page.start=decode.page.index;
codepage->AddCacheBlock(decode.block);
gen_save_host_direct(&cache.block.running,(Bit32u)decode.block);
for (i=0;i<G_MAX;i++) {
DynRegs[i].flags&=~(DYNFLG_ACTIVE|DYNFLG_CHANGED);
DynRegs[i].genreg=0;
}
gen_reinit();
gen_save_host_direct(&cache.block.running,(Bitu)decode.block);
/* Start with the cycles check */
gen_protectflags();
gen_dop_word_imm(DOP_CMP,true,DREG(CYCLES),0);
gen_dop_word(DOP_TEST,true,DREG(CYCLES),DREG(CYCLES));
save_info[used_save_info].branch_pos=gen_create_branch_long(BR_LE);
save_info[used_save_info].type=cycle_check;
used_save_info++;
@ -2370,7 +2464,9 @@ restart_prefix:
case 0xca:dyn_ret_far(decode_fetchw());goto finish_block;
case 0xcb:dyn_ret_far(0);goto finish_block;
/* Interrupt */
// case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
#if !(C_DEBUG)
case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
#endif
/* IRET */
case 0xcf:dyn_iret();goto finish_block;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -64,29 +64,29 @@ static void dyn_eatree() {
Bitu group=(decode.modrm.val >> 3) & 7;
switch (group){
case 0x00: /* FADD ST,STi */
gen_call_function((void*)&FPU_FADD_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FADD_EA,"%Drd",DREG(TMPB));
break;
case 0x01: /* FMUL ST,STi */
gen_call_function((void*)&FPU_FMUL_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FMUL_EA,"%Drd",DREG(TMPB));
break;
case 0x02: /* FCOM STi */
gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
break;
case 0x03: /* FCOMP STi */
gen_call_function((void*)&FPU_FCOM_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FCOM_EA,"%Drd",DREG(TMPB));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FSUB ST,STi */
gen_call_function((void*)&FPU_FSUB_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FSUB_EA,"%Drd",DREG(TMPB));
break;
case 0x05: /* FSUBR ST,STi */
gen_call_function((void*)&FPU_FSUBR_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR_EA,"%Drd",DREG(TMPB));
break;
case 0x06: /* FDIV ST,STi */
gen_call_function((void*)&FPU_FDIV_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FDIV_EA,"%Drd",DREG(TMPB));
break;
case 0x07: /* FDIVR ST,STi */
gen_call_function((void*)&FPU_FDIVR_EA,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR_EA,"%Drd",DREG(TMPB));
break;
default:
break;
@ -98,39 +98,39 @@ static void dyn_fpu_esc0(){
if (decode.modrm.val >= 0xc0) {
dyn_fpu_top();
Bitu group=(decode.modrm.val >> 3) & 7;
Bitu sub=(decode.modrm.val & 7);
//Bitu sub=(decode.modrm.val & 7);
switch (group){
case 0x00: //FADD ST,STi /
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x01: // FMUL ST,STi /
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: // FCOM STi /
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: // FCOMP STi /
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: // FSUB ST,STi /
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x05: // FSUBR ST,STi /
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x06: // FDIV ST,STi /
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x07: // FDIVR ST,STi /
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
default:
break;
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_F32_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F32_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -149,18 +149,18 @@ static void dyn_fpu_esc1(){
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FXCH STi */
dyn_fpu_top();
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FNOP */
gen_call_function((void*)&FPU_FNOP,"");
break;
case 0x03: /* FSTP STi */
dyn_fpu_top();
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04:
@ -290,29 +290,29 @@ static void dyn_fpu_esc1(){
gen_protectflags();
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_F32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_F32,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST float*/
gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP float*/
gen_call_function((void*)&FPU_FST_F32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F32,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FLDENV */
gen_call_function((void*)&FPU_FLDENV,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLDENV,"%Drd",DREG(EA));
break;
case 0x05: /* FLDCW */
gen_call_function((void *)&FPU_FLDCW,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FLDCW,"%Drd",DREG(EA));
break;
case 0x06: /* FSTENV */
gen_call_function((void *)&FPU_FSTENV,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FSTENV,"%Drd",DREG(EA));
break;
case 0x07: /* FNSTCW*/
gen_call_function((void *)&FPU_FNSTCW,"%Ddr",DREG(EA));
gen_call_function((void *)&FPU_FNSTCW,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
@ -335,7 +335,7 @@ static void dyn_fpu_esc2(){
gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void *)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void *)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void *)&FPU_FPOP,"");
gen_call_function((void *)&FPU_FPOP,"");
break;
@ -350,7 +350,7 @@ static void dyn_fpu_esc2(){
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_I32_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_I32_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -395,24 +395,24 @@ static void dyn_fpu_esc3(){
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I32,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I32,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FISTTP */
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST */
gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP */
gen_call_function((void*)&FPU_FST_I32,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I32,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x05: /* FLD 80 Bits Real */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_call_function((void*)&FPU_FLD_F80,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F80,"%Drd",DREG(EA));
break;
case 0x07: /* FSTP 80 Bits Real */
gen_call_function((void*)&FPU_FST_F80,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F80,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:
@ -424,41 +424,41 @@ static void dyn_fpu_esc3(){
static void dyn_fpu_esc4(){
dyn_get_modrm();
Bitu group=(decode.modrm.val >> 3) & 7;
Bitu sub=(decode.modrm.val & 7);
//Bitu sub=(decode.modrm.val & 7);
if (decode.modrm.val >= 0xc0) {
dyn_fpu_top();
switch(group){
case 0x00: /* FADD STi,ST*/
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FMUL STi,ST*/
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x02: /* FCOM*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: /* FCOMP*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FSUBR STi,ST*/
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FSUB STi,ST*/
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FDIVR STi,ST*/
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x07: /* FDIV STi,ST*/
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
break;
}
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_F64_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_F64_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -472,23 +472,23 @@ static void dyn_fpu_esc5(){
dyn_fpu_top();
switch(group){
case 0x00: /* FFREE STi */
gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
break;
case 0x01: /* FXCH STi*/
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FST STi */
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x03: /* FSTP STi*/
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FUCOM STi */
gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x05: /*FUCOMP STi */
gen_call_function((void*)&FPU_FUCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FUCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:
@ -504,30 +504,30 @@ static void dyn_fpu_esc5(){
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_F64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_F64,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FISTTP longint*/
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST double real*/
gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP double real*/
gen_call_function((void*)&FPU_FST_F64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_F64,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FRSTOR */
gen_call_function((void*)&FPU_FRSTOR,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FRSTOR,"%Drd",DREG(EA));
break;
case 0x06: /* FSAVE */
gen_call_function((void*)&FPU_FSAVE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FSAVE,"%Drd",DREG(EA));
break;
case 0x07: /*FNSTSW */
gen_protectflags();
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_SET_TOP,"%Dd",DREG(TMPB));
gen_load_host(&fpu.sw,DREG(TMPB),4);
gen_call_function((void*)&mem_writew,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&mem_writew,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
@ -543,13 +543,13 @@ static void dyn_fpu_esc6(){
dyn_fpu_top();
switch(group){
case 0x00: /*FADDP STi,ST*/
gen_call_function((void*)&FPU_FADD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FADD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01: /* FMULP STi,ST*/
gen_call_function((void*)&FPU_FMUL,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FMUL,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x02: /* FCOMP5*/
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
break; /* TODO IS THIS ALLRIGHT ????????? */
case 0x03: /*FCOMPP*/
if(sub != 1) {
@ -559,20 +559,20 @@ static void dyn_fpu_esc6(){
gen_load_host(&TOP,DREG(EA),4);
gen_dop_word_imm(DOP_ADD,true,DREG(EA),1);
gen_dop_word_imm(DOP_AND,true,DREG(EA),7);
gen_call_function((void*)&FPU_FCOM,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FCOM,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,""); /* extra pop at the bottom*/
break;
case 0x04: /* FSUBRP STi,ST*/
gen_call_function((void*)&FPU_FSUBR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUBR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FSUBP STi,ST*/
gen_call_function((void*)&FPU_FSUB,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FSUB,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FDIVRP STi,ST*/
gen_call_function((void*)&FPU_FDIVR,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIVR,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x07: /* FDIVP STi,ST*/
gen_call_function((void*)&FPU_FDIV,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FDIV,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
default:
break;
@ -580,7 +580,7 @@ static void dyn_fpu_esc6(){
gen_call_function((void*)&FPU_FPOP,"");
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_I16_EA,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FLD_I16_EA,"%Drd",DREG(EA));
gen_load_host(&TOP,DREG(TMPB),4);
dyn_eatree();
}
@ -594,24 +594,24 @@ static void dyn_fpu_esc7(){
switch (group){
case 0x00: /* FFREEP STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FFREE,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FFREE,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x01: /* FXCH STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FXCH,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FXCH,"%Drd%Drd",DREG(TMPB),DREG(EA));
break;
case 0x02: /* FSTP STi*/
case 0x03: /* FSTP STi*/
dyn_fpu_top();
gen_call_function((void*)&FPU_FST,"%Ddr%Ddr",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FST,"%Drd%Drd",DREG(TMPB),DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04:
switch(sub){
case 0x00: /* FNSTSW AX*/
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_SET_TOP,"%Ddr",DREG(TMPB));
gen_call_function((void*)&FPU_SET_TOP,"%Drd",DREG(TMPB));
gen_mov_host(&fpu.sw,DREG(EAX),2);
break;
default:
@ -629,34 +629,34 @@ static void dyn_fpu_esc7(){
case 0x00: /* FILD Bit16s */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I16,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I16,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x01:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST Bit16s */
gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP Bit16s */
gen_call_function((void*)&FPU_FST_I16,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I16,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x04: /* FBLD packed BCD */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FBLD,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FBLD,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x05: /* FILD Bit64s */
gen_call_function((void*)&FPU_PREP_PUSH,"");
gen_load_host(&TOP,DREG(TMPB),4);
gen_call_function((void*)&FPU_FLD_I64,"%Ddr%Ddr",DREG(EA),DREG(TMPB));
gen_call_function((void*)&FPU_FLD_I64,"%Drd%Drd",DREG(EA),DREG(TMPB));
break;
case 0x06: /* FBSTP packed BCD */
gen_call_function((void*)&FPU_FBST,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FBST,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
case 0x07: /* FISTP Bit64s */
gen_call_function((void*)&FPU_FST_I64,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FST_I64,"%Drd",DREG(EA));
gen_call_function((void*)&FPU_FPOP,"");
break;
default:

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -148,6 +148,16 @@ static void FPU_FRSTOR_DH(PhysPt addr){
}
}
static void dh_fpu_mem(Bit8u inst, Bitu reg=decode.modrm.reg, void* mem=&dyn_dh_fpu.temp.m1) {
#if C_TARGETCPU == X86
cache_addb(inst);
cache_addb(0x05|(reg<<3));
cache_addd((Bit32u)(mem));
#else // X86_64
opcode(reg).setabsaddr(mem).Emit8(inst);
#endif
}
static void dh_fpu_esc0(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
@ -155,10 +165,8 @@ static void dh_fpu_esc0(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xd8);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xd8);
}
}
@ -173,46 +181,34 @@ static void dh_fpu_esc1(){
dyn_fill_ea();
switch(group){
case 0x00: /* FLD float*/
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x01: /* UNKNOWN */
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST float*/
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP float*/
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x04: /* FLDENV */
gen_call_function((void*)&FPU_FLDENV_DH,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLDENV_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x05: /* FLDCW */
gen_call_function((void *)&FPU_FLDCW_DH,"%Ddr",DREG(EA));
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void *)&FPU_FLDCW_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xd9);
break;
case 0x06: /* FSTENV */
cache_addb(0xd9);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FSTENV_DH,"%Ddr",DREG(EA));
dh_fpu_mem(0xd9);
gen_call_function((void*)&FPU_FSTENV_DH,"%Drd",DREG(EA));
break;
case 0x07: /* FNSTCW*/
gen_call_function((void*)&FPU_FNSTCW_DH,"%Ddr",DREG(EA));
gen_call_function((void*)&FPU_FNSTCW_DH,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",group,sub);
@ -228,10 +224,8 @@ static void dh_fpu_esc2(){
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xda);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xda);
}
}
@ -274,37 +268,27 @@ static void dh_fpu_esc3(){
dyn_fill_ea();
switch(group){
case 0x00: /* FILD */
gen_call_function((void*)&FPU_FLD_32,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_32,"%Drd",DREG(EA));
dh_fpu_mem(0xdb);
break;
case 0x01: /* FISTTP */
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_32,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_32,"%Drd",DREG(EA));
break;
case 0x05: /* FLD 80 Bits Real */
gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_80,"%Drd",DREG(EA));
dh_fpu_mem(0xdb);
break;
case 0x07: /* FSTP 80 Bits Real */
cache_addb(0xdb);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
dh_fpu_mem(0xdb);
gen_call_function((void*)&FPU_FST_80,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",group,sub);
@ -314,17 +298,13 @@ static void dh_fpu_esc3(){
static void dh_fpu_esc4(){
dyn_get_modrm();
Bitu group=(decode.modrm.val >> 3) & 7;
Bitu sub=(decode.modrm.val & 7);
if (decode.modrm.val >= 0xc0) {
cache_addb(0xdc);
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdc);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdc);
}
}
@ -339,45 +319,32 @@ static void dh_fpu_esc5(){
Bitu sub=(decode.modrm.val & 7);
switch(group){
case 0x00: /* FLD double real*/
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdd);
break;
case 0x01: /* FISTTP longint*/
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FST double real*/
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
case 0x03: /* FSTP double real*/
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
case 0x04: /* FRSTOR */
gen_call_function((void*)&FPU_FRSTOR_DH,"%Ddr",DREG(EA));
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
gen_call_function((void*)&FPU_FRSTOR_DH,"%Drd",DREG(EA));
dh_fpu_mem(0xdd, decode.modrm.reg, &(dyn_dh_fpu.temp_state[0]));
break;
case 0x06: /* FSAVE */
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp_state[0])));
gen_call_function((void*)&FPU_FSAVE_DH,"%Ddr",DREG(EA));
cache_addb(0xdb);
cache_addb(0xe3);
dh_fpu_mem(0xdd, decode.modrm.reg, &(dyn_dh_fpu.temp_state[0]));
gen_call_function((void*)&FPU_FSAVE_DH,"%Drd",DREG(EA));
cache_addw(0xE3DB);
break;
case 0x07: /* FNSTSW */
cache_addb(0xdd);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdd);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",group,sub);
@ -387,17 +354,13 @@ static void dh_fpu_esc5(){
static void dh_fpu_esc6(){
dyn_get_modrm();
Bitu group=(decode.modrm.val >> 3) & 7;
Bitu sub=(decode.modrm.val & 7);
if (decode.modrm.val >= 0xc0) {
cache_addb(0xde);
cache_addb(decode.modrm.val);
} else {
dyn_fill_ea();
gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA));
cache_addb(0xde);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_16,"%Drd",DREG(EA));
dh_fpu_mem(0xde);
}
}
@ -423,9 +386,7 @@ static void dh_fpu_esc7(){
case 0x04:
switch(sub){
case 0x00: /* FNSTSW AX*/
cache_addb(0xdd);
cache_addb(0x05|(0x07<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
dh_fpu_mem(0xdd, 7);
gen_load_host(&(dyn_dh_fpu.temp.m1),DREG(TMPB),4);
gen_dop_word(DOP_MOV,false,DREG(EAX),DREG(TMPB));
gen_releasereg(DREG(TMPB));
@ -443,49 +404,35 @@ static void dh_fpu_esc7(){
dyn_fill_ea();
switch(group){
case 0x00: /* FILD Bit16s */
gen_call_function((void*)&FPU_FLD_16,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_16,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x01:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);
break;
case 0x02: /* FIST Bit16s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
case 0x03: /* FISTP Bit16s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_16,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_16,"%Drd",DREG(EA));
break;
case 0x04: /* FBLD packed BCD */
gen_call_function((void*)&FPU_FLD_80,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_80,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x05: /* FILD Bit64s */
gen_call_function((void*)&FPU_FLD_64,"%Ddr",DREG(EA));
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FLD_64,"%Drd",DREG(EA));
dh_fpu_mem(0xdf);
break;
case 0x06: /* FBSTP packed BCD */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_80,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_80,"%Drd",DREG(EA));
break;
case 0x07: /* FISTP Bit64s */
cache_addb(0xdf);
cache_addb(0x05|(decode.modrm.reg<<3));
cache_addd((Bit32u)(&(dyn_dh_fpu.temp.m1)));
gen_call_function((void*)&FPU_FST_64,"%Ddr",DREG(EA));
dh_fpu_mem(0xdf);
gen_call_function((void*)&FPU_FST_64,"%Drd",DREG(EA));
break;
default:
LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",group,sub);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
static bool dyn_helper_divb(Bit8u val) {
@ -40,8 +40,8 @@ static bool dyn_helper_idivb(Bit8s val) {
static bool dyn_helper_divw(Bit16u val) {
if (!val) return CPU_PrepareException(0,0);
Bitu num=(reg_dx<<16)|reg_ax;
Bitu quo=num/val;
Bit32u num=(((Bit32u)reg_dx)<<16)|reg_ax;
Bit32u quo=num/val;
Bit16u rem=(Bit16u)(num % val);
Bit16u quo16=(Bit16u)(quo&0xffff);
if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0);
@ -52,8 +52,8 @@ static bool dyn_helper_divw(Bit16u val) {
static bool dyn_helper_idivw(Bit16s val) {
if (!val) return CPU_PrepareException(0,0);
Bits num=(reg_dx<<16)|reg_ax;
Bits quo=num/val;
Bit32s num=(((Bit32u)reg_dx)<<16)|reg_ax;
Bit32s quo=num/val;
Bit16s rem=(Bit16s)(num % val);
Bit16s quo16s=(Bit16s)quo;
if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -311,16 +311,16 @@ static void gen_load_host(void * data,DynReg * dr1,Bitu size) {
dr1->flags|=DYNFLG_CHANGED;
}
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bit8u di1=0) {
static void gen_mov_host(void * data,DynReg * dr1,Bitu size,Bitu di1=0) {
GenReg * gr1=FindDynReg(dr1,(size==4));
switch (size) {
case 1:cache_addb(0x8a);break; //mov byte
case 2:cache_addb(0x66); //mov word
case 4:cache_addb(0x8b);break; //mov
default:
IllegalOption("gen_load_host");
IllegalOption("gen_mov_host");
}
cache_addb(0x5+((gr1->index+(di1?4:0))<<3));
cache_addb(0x5+((gr1->index+di1)<<3));
cache_addd((Bit32u)data);
dr1->flags|=DYNFLG_CHANGED;
}
@ -388,7 +388,7 @@ static void gen_dop_byte_imm_mem(DualOps op,DynReg * dr1,Bit8u di1,void* data) {
case DOP_AND: tmp=0x0522; break;
case DOP_OR: tmp=0x050a; break;
case DOP_TEST: tmp=0x0584; goto nochange; //Doesn't change
case DOP_MOV: tmp=0x0585; break;
case DOP_MOV: tmp=0x058A; break;
default:
IllegalOption("gen_dop_byte_imm_mem");
}
@ -769,6 +769,7 @@ static void gen_call_function(void * func,char const* ops,...) {
}
ops++;
}
va_end(params);
#if defined (MACOSX)
/* align stack */
@ -1068,4 +1069,28 @@ static void gen_init(void) {
x86gen.regs[X86_REG_EDI]=new GenReg(7);
}
#if defined(X86_DYNFPU_DH_ENABLED)
static void gen_dh_fpu_save(void)
#if defined (_MSC_VER)
{
__asm {
__asm fnsave dyn_dh_fpu.state
__asm fldcw dyn_dh_fpu.host_cw
}
dyn_dh_fpu.state_used=false;
dyn_dh_fpu.state.cw|=0x3f;
}
#else
{
__asm__ volatile (
"fnsave %0 \n"
"fldcw %1 \n"
: "=m" (dyn_dh_fpu.state)
: "m" (dyn_dh_fpu.host_cw)
: "memory"
);
dyn_dh_fpu.state_used=false;
dyn_dh_fpu.state.cw|=0x3f;
}
#endif
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
enum STRING_OP {
@ -82,7 +82,7 @@ static void dyn_string(STRING_OP op) {
Bit8u * rep_ecx_jmp;
/* Check if ECX!=zero */
if (decode.rep) {
gen_dop_word(DOP_OR,decode.big_addr,DREG(ECX),DREG(ECX));
gen_dop_word(DOP_TEST,decode.big_addr,DREG(ECX),DREG(ECX));
rep_ecx_jmp=gen_create_branch_long(BR_Z);
}
if (usesi) {
@ -99,11 +99,11 @@ static void dyn_string(STRING_OP op) {
}
switch (op) {
case STR_OUTSB:
gen_call_function((void*)&IO_WriteB,"%Id%Dl",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteB,"%Dw%Dl",DREG(EDX),tmp_reg);break;
case STR_OUTSW:
gen_call_function((void*)&IO_WriteW,"%Id%Dw",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteW,"%Dw%Dw",DREG(EDX),tmp_reg);break;
case STR_OUTSD:
gen_call_function((void*)&IO_WriteD,"%Id%Dd",DREG(EDX),tmp_reg);break;
gen_call_function((void*)&IO_WriteD,"%Dw%Dd",DREG(EDX),tmp_reg);break;
}
}
if (usedi) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -137,7 +137,8 @@ static struct {
#define X86_64 0x02
#define MIPSEL 0x03
#define ARMV4LE 0x04
#define POWERPC 0x04
#define ARMV7LE 0x05
#define ARMV8LE 0x07
#if C_TARGETCPU == X86_64
#include "core_dynrec/risc_x64.h"
@ -145,10 +146,10 @@ static struct {
#include "core_dynrec/risc_x86.h"
#elif C_TARGETCPU == MIPSEL
#include "core_dynrec/risc_mipsel32.h"
#elif C_TARGETCPU == ARMV4LE
#elif (C_TARGETCPU == ARMV4LE) || (C_TARGETCPU == ARMV7LE)
#include "core_dynrec/risc_armv4le.h"
#elif C_TARGETCPU == POWERPC
#include "core_dynrec/risc_ppc.h"
#elif C_TARGETCPU == ARMV8LE
#include "core_dynrec/risc_armv8le.h"
#endif
#include "core_dynrec/decoder.h"
@ -158,16 +159,14 @@ CacheBlockDynRec * LinkBlocks(BlockReturn ret) {
// the last instruction was a control flow modifying instruction
Bitu temp_ip=SegPhys(cs)+reg_eip;
CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)get_tlb_readhandler(temp_ip);
if (temp_handler->flags & PFLAG_HASCODE) {
if (temp_handler->flags & (cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16)) {
// see if the target is an already translated block
block=temp_handler->FindCacheBlock(temp_ip & 4095);
if (!block) return NULL;
// found it, link the current block to
cache.block.running->LinkTo(ret==BR_Link2,block);
return block;
if (block) { // found it, link the current block to
cache.block.running->LinkTo(ret==BR_Link2,block);
}
}
return NULL;
return block;
}
/*
@ -219,7 +218,7 @@ Bits CPU_Core_Dynrec_Run(void) {
continue;
}
CPU_CycleLeft+=old_cycles;
return nc_retcode;
return nc_retcode;
}
}
@ -231,8 +230,10 @@ run_block:
switch (ret) {
case BR_Iret:
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#endif
if (!GETFLAG(TF)) {
if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
@ -247,16 +248,20 @@ run_block:
// modifying instruction (like ret) or some nontrivial cpu state
// changing instruction (for example switch to/from pmode),
// or the maximum number of instructions to translate was reached
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#endif
break;
case BR_Cycles:
// cycles went negative, return from the core to handle
// external events, schedule the pic...
#if C_HEAVY_DEBUG
#if C_DEBUG
#if C_HEAVY_DEBUG
if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
#endif
return CBRET_NONE;

View File

@ -1,5 +1,5 @@
noinst_HEADERS = cache.h decoder.h decoder_basic.h decoder_opcodes.h \
dyn_fpu.h operators.h risc_x64.h risc_x86.h risc_mipsel32.h \
risc_armv4le.h risc_armv4le-common.h \
risc_armv4le-s3.h risc_armv4le-o3.h risc_armv4le-thumb.h \
risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h
risc_armv4le-o3.h risc_armv4le-thumb.h \
risc_armv4le-thumb-iw.h risc_armv4le-thumb-niw.h risc_armv8le.h

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -96,7 +96,7 @@ public:
old_pagehandler=_old_pagehandler;
// adjust flags
flags=old_pagehandler->flags|PFLAG_HASCODE;
flags=old_pagehandler->flags|(cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16);
flags&=~PFLAG_WRITEABLE;
active_blocks=0;
@ -596,14 +596,14 @@ static void cache_init(bool enable) {
if(!cache_code_start_ptr) E_Exit("Allocating dynamic cache failed");
// align the cache at a page boundary
cache_code=(Bit8u*)(((long)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1)); //MEM LEAK. store old pointer if you want to free it.
cache_code=(Bit8u*)(((Bitu)cache_code_start_ptr + PAGESIZE_TEMP-1) & ~(PAGESIZE_TEMP-1));//Bitu is same size as a pointer.
cache_code_link_blocks=cache_code;
cache_code=cache_code+PAGESIZE_TEMP;
#if (C_HAVE_MPROTECT)
if(mprotect(cache_code_link_blocks,CACHE_TOTAL+CACHE_MAXSIZE+PAGESIZE_TEMP,PROT_WRITE|PROT_READ|PROT_EXEC))
LOG_MSG("Setting excute permission on the code cache has failed");
LOG_MSG("Setting execute permission on the code cache has failed");
#endif
CacheBlockDynRec * block=cache_getblock();
cache.block.first=block;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -446,7 +446,9 @@ restart_prefix:
case 0xcb:dyn_ret_far(0);goto finish_block;
// int/iret
#if !(C_DEBUG)
case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block;
#endif
case 0xcf:dyn_iret();goto finish_block;
// case 0xd4: AAM missing

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -120,7 +120,7 @@ static struct DynDecode {
// modrm state of the current instruction (if used)
struct {
Bitu val;
// Bitu val;
Bitu mod;
Bitu rm;
Bitu reg;
@ -130,21 +130,30 @@ static struct DynDecode {
static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) {
Bit8u rdval;
const Bitu cflag = cpu.code.big ? PFLAG_HASCODE32:PFLAG_HASCODE16;
//Ensure page contains memory:
if (GCC_UNLIKELY(mem_readb_checked(lin_addr,&rdval))) return true;
PageHandler * handler=get_tlb_readhandler(lin_addr);
if (handler->flags & PFLAG_HASCODE) {
// this is a codepage handler, and the one that we're looking for
// this is a codepage handler, make sure it matches current code size
cph=(CodePageHandlerDynRec *)handler;
return false;
if (handler->flags & cflag) return false;
// wrong code size/stale dynamic code, drop it
cph->ClearRelease();
cph=0;
// handler was changed, refresh
handler=get_tlb_readhandler(lin_addr);
}
if (handler->flags & PFLAG_NOCODE) {
if (PAGING_ForcePageInit(lin_addr)) {
handler=get_tlb_readhandler(lin_addr);
if (handler->flags & PFLAG_HASCODE) {
cph=(CodePageHandlerDynRec *)handler;
return false;
if (handler->flags & cflag) return false;
cph->ClearRelease();
cph=0;
handler=get_tlb_readhandler(lin_addr);
}
}
if (handler->flags & PFLAG_NOCODE) {
@ -372,10 +381,10 @@ static bool decode_fetchd_imm(Bitu & val) {
// modrm decoding helper
static void INLINE dyn_get_modrm(void) {
decode.modrm.val=decode_fetchb();
decode.modrm.mod=(decode.modrm.val >> 6) & 3;
decode.modrm.reg=(decode.modrm.val >> 3) & 7;
decode.modrm.rm=(decode.modrm.val & 7);
Bitu val=decode_fetchb();
decode.modrm.mod=(val >> 6) & 3;
decode.modrm.reg=(val >> 3) & 7;
decode.modrm.rm=(val & 7);
}
@ -490,7 +499,8 @@ static INLINE void dyn_set_eip_end(void) {
// set reg_eip to the start of the next instruction plus an offset (imm)
static INLINE void dyn_set_eip_end(HostReg reg,Bit32u imm=0) {
gen_mov_word_to_reg(reg,&reg_eip,decode.big_op);
gen_mov_word_to_reg(reg,&reg_eip,true); //get_extend_word will mask off the upper bits
//gen_mov_word_to_reg(reg,&reg_eip,decode.big_op);
gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start+imm));
if (!decode.big_op) gen_extend_word(false,reg);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -444,14 +444,23 @@ static void dyn_push_word_imm(Bitu imm) {
static void dyn_pop_ev(void) {
dyn_get_modrm();
if (decode.modrm.mod<3) {
/* dyn_fill_ea(FC_ADDR);
gen_protect_addr_reg();
dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); // dummy read to trigger possible page faults */
// save original ESP
MOV_REG_WORD32_TO_HOST_REG(FC_OP2,DRC_REG_ESP);
gen_protect_reg(FC_OP2);
if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
else gen_call_function_raw((void*)&dynrec_pop_word);
dyn_fill_ea(FC_ADDR);
// gen_restore_addr_reg();
dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op);
gen_mov_regs(FC_OP2,FC_RETOP);
gen_mov_regs(FC_OP1,FC_ADDR);
if (decode.big_op) gen_call_function_raw((void *)&mem_writed_checked_drc);
else gen_call_function_raw((void *)&mem_writew_checked_drc);
gen_extend_byte(false,FC_RETOP); // bool -> dword
DRC_PTR_SIZE_IM no_fault = gen_create_branch_on_zero(FC_RETOP, true);
// restore original ESP
gen_restore_reg(FC_OP2);
MOV_REG_WORD32_FROM_HOST_REG(FC_OP2,DRC_REG_ESP);
dyn_check_exception(FC_RETOP);
gen_fill_branch(no_fault);
} else {
if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword);
else gen_call_function_raw((void*)&dynrec_pop_word);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -68,7 +68,8 @@ static INLINE void dyn_fpu_top_swapped() {
}
static void dyn_eatree() {
Bitu group=(decode.modrm.val >> 3) & 7;
// Bitu group = (decode.modrm.val >> 3) & 7;
Bitu group = decode.modrm.reg&7; //It is already that, but compilers.
switch (group){
case 0x00: // FADD ST,STi
gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1);
@ -102,7 +103,8 @@ static void dyn_eatree() {
static void dyn_fpu_esc0(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
dyn_fpu_top();
switch (decode.modrm.reg){
case 0x00: //FADD ST,STi
@ -144,7 +146,8 @@ static void dyn_fpu_esc0(){
static void dyn_fpu_esc1(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch (decode.modrm.reg){
case 0x00: /* FLD STi */
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
@ -331,7 +334,8 @@ static void dyn_fpu_esc1(){
static void dyn_fpu_esc2(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch(decode.modrm.reg){
case 0x05:
switch(decode.modrm.rm){
@ -363,7 +367,8 @@ static void dyn_fpu_esc2(){
static void dyn_fpu_esc3(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch (decode.modrm.reg) {
case 0x04:
switch (decode.modrm.rm) {
@ -427,7 +432,8 @@ static void dyn_fpu_esc3(){
static void dyn_fpu_esc4(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch(decode.modrm.reg){
case 0x00: /* FADD STi,ST*/
dyn_fpu_top_swapped();
@ -475,7 +481,8 @@ static void dyn_fpu_esc4(){
static void dyn_fpu_esc5(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
dyn_fpu_top();
switch(decode.modrm.reg){
case 0x00: /* FFREE STi */
@ -534,7 +541,7 @@ static void dyn_fpu_esc5(){
gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true);
gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1);
dyn_fill_ea(FC_OP1);
gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true);
gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),false);
gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2);
break;
default:
@ -545,7 +552,8 @@ static void dyn_fpu_esc5(){
static void dyn_fpu_esc6(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch(decode.modrm.reg){
case 0x00: /*FADDP STi,ST*/
dyn_fpu_top_swapped();
@ -601,7 +609,8 @@ static void dyn_fpu_esc6(){
static void dyn_fpu_esc7(){
dyn_get_modrm();
if (decode.modrm.val >= 0xc0) {
// if (decode.modrm.val >= 0xc0) {
if (decode.modrm.mod == 3) {
switch (decode.modrm.reg){
case 0x00: /* FFREEP STi */
dyn_fpu_top();

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,918 +0,0 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* ARMv4 (little endian) backend by M-HT (speed-tweaked arm version) */
// temporary registers
#define temp1 HOST_ip
#define temp2 HOST_v3
#define temp3 HOST_v4
// register that holds function return values
#define FC_RETOP HOST_a1
// register used for address calculations,
#define FC_ADDR HOST_v1 // has to be saved across calls, see DRC_PROTECT_ADDR_REG
// register that holds the first parameter
#define FC_OP1 HOST_a1
// register that holds the second parameter
#define FC_OP2 HOST_a2
// special register that holds the third parameter for _R3 calls (byte accessible)
#define FC_OP3 HOST_v2
// register that holds byte-accessible temporary values
#define FC_TMP_BA1 HOST_a1
// register that holds byte-accessible temporary values
#define FC_TMP_BA2 HOST_a2
// temporary register for LEA
#define TEMP_REG_DRC HOST_v2
#ifdef DRC_USE_REGS_ADDR
// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
#define FC_REGS_ADDR HOST_v7
#endif
#ifdef DRC_USE_SEGS_ADDR
// used to hold the address of "Segs" - preferably filled in function gen_run_code
#define FC_SEGS_ADDR HOST_v8
#endif
// helper macro
#define ROTATE_SCALE(x) ( (x)?(32 - x):(0) )
// instruction encodings
// move
// mov dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define MOV_IMM(dst, imm, rimm) (0xe3a00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
// mov dst, src, lsl #imm
#define MOV_REG_LSL_IMM(dst, src, imm) (0xe1a00000 + ((dst) << 12) + (src) + ((imm) << 7) )
// movs dst, src, lsl #imm
#define MOVS_REG_LSL_IMM(dst, src, imm) (0xe1b00000 + ((dst) << 12) + (src) + ((imm) << 7) )
// mov dst, src, lsr #imm
#define MOV_REG_LSR_IMM(dst, src, imm) (0xe1a00020 + ((dst) << 12) + (src) + ((imm) << 7) )
// mov dst, src, asr #imm
#define MOV_REG_ASR_IMM(dst, src, imm) (0xe1a00040 + ((dst) << 12) + (src) + ((imm) << 7) )
// mov dst, src, lsl rreg
#define MOV_REG_LSL_REG(dst, src, rreg) (0xe1a00010 + ((dst) << 12) + (src) + ((rreg) << 8) )
// mov dst, src, lsr rreg
#define MOV_REG_LSR_REG(dst, src, rreg) (0xe1a00030 + ((dst) << 12) + (src) + ((rreg) << 8) )
// mov dst, src, asr rreg
#define MOV_REG_ASR_REG(dst, src, rreg) (0xe1a00050 + ((dst) << 12) + (src) + ((rreg) << 8) )
// mov dst, src, ror rreg
#define MOV_REG_ROR_REG(dst, src, rreg) (0xe1a00070 + ((dst) << 12) + (src) + ((rreg) << 8) )
// mvn dst, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define MVN_IMM(dst, imm, rimm) (0xe3e00000 + ((dst) << 12) + (imm) + ((rimm) << 7) )
// arithmetic
// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// add dst, src1, src2, lsl #imm
#define ADD_REG_LSL_IMM(dst, src1, src2, imm) (0xe0800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// sub dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define SUB_IMM(dst, src, imm, rimm) (0xe2400000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// sub dst, src1, src2, lsl #imm
#define SUB_REG_LSL_IMM(dst, src1, src2, imm) (0xe0400000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// rsb dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define RSB_IMM(dst, src, imm, rimm) (0xe2600000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// cmp src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define CMP_IMM(src, imm, rimm) (0xe3500000 + ((src) << 16) + (imm) + ((rimm) << 7) )
// nop
#define NOP MOV_REG_LSL_IMM(HOST_r0, HOST_r0, 0)
// logical
// tst src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define TST_IMM(src, imm, rimm) (0xe3100000 + ((src) << 16) + (imm) + ((rimm) << 7) )
// and dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define AND_IMM(dst, src, imm, rimm) (0xe2000000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// and dst, src1, src2, lsl #imm
#define AND_REG_LSL_IMM(dst, src1, src2, imm) (0xe0000000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// orr dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define ORR_IMM(dst, src, imm, rimm) (0xe3800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// orr dst, src1, src2, lsl #imm
#define ORR_REG_LSL_IMM(dst, src1, src2, imm) (0xe1800000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// orr dst, src1, src2, lsr #imm
#define ORR_REG_LSR_IMM(dst, src1, src2, imm) (0xe1800020 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// eor dst, src1, src2, lsl #imm
#define EOR_REG_LSL_IMM(dst, src1, src2, imm) (0xe0200000 + ((dst) << 12) + ((src1) << 16) + (src2) + ((imm) << 7) )
// bic dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define BIC_IMM(dst, src, imm, rimm) (0xe3c00000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// load
// ldr reg, [addr, #imm] @ 0 <= imm < 4096
#define LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// ldrh reg, [addr, #imm] @ 0 <= imm < 256
#define LDRH_IMM(reg, addr, imm) (0xe1d000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
// ldrb reg, [addr, #imm] @ 0 <= imm < 4096
#define LDRB_IMM(reg, addr, imm) (0xe5d00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// store
// str reg, [addr, #imm] @ 0 <= imm < 4096
#define STR_IMM(reg, addr, imm) (0xe5800000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// strh reg, [addr, #imm] @ 0 <= imm < 256
#define STRH_IMM(reg, addr, imm) (0xe1c000b0 + ((reg) << 12) + ((addr) << 16) + (((imm) & 0xf0) << 4) + ((imm) & 0x0f) )
// strb reg, [addr, #imm] @ 0 <= imm < 4096
#define STRB_IMM(reg, addr, imm) (0xe5c00000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// branch
// beq pc+imm @ 0 <= imm < 32M & imm mod 4 = 0
#define BEQ_FWD(imm) (0x0a000000 + ((imm) >> 2) )
// bne pc+imm @ 0 <= imm < 32M & imm mod 4 = 0
#define BNE_FWD(imm) (0x1a000000 + ((imm) >> 2) )
// bgt pc+imm @ 0 <= imm < 32M & imm mod 4 = 0
#define BGT_FWD(imm) (0xca000000 + ((imm) >> 2) )
// b pc+imm @ 0 <= imm < 32M & imm mod 4 = 0
#define B_FWD(imm) (0xea000000 + ((imm) >> 2) )
// bx reg
#define BX(reg) (0xe12fff10 + (reg) )
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
if(reg_src == reg_dst) return;
cache_addd( MOV_REG_LSL_IMM(reg_dst, reg_src, 0) ); // mov reg_dst, reg_src
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
Bits first, scale;
if (imm == 0) {
cache_addd( MOV_IMM(dest_reg, 0, 0) ); // mov dest_reg, #0
} else {
scale = 0;
first = 1;
while (imm) {
while ((imm & 3) == 0) {
imm>>=2;
scale+=2;
}
if (first) {
cache_addd( MOV_IMM(dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // mov dest_reg, #((imm & 0xff) << scale)
first = 0;
} else {
cache_addd( ORR_IMM(dest_reg, dest_reg, imm & 0xff, ROTATE_SCALE(scale)) ); // orr dest_reg, dest_reg, #((imm & 0xff) << scale)
}
imm>>=8;
scale+=8;
}
}
}
// helper function for gen_mov_word_to_reg
static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
// alignment....
if (dword) {
if ((Bit32u)data & 3) {
if ( ((Bit32u)data & 3) == 2 ) {
cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
cache_addd( LDRH_IMM(temp2, data_reg, 2) ); // ldrh temp2, [data_reg, #2]
cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 16) ); // orr dest_reg, dest_reg, temp2, lsl #16
} else {
cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg]
cache_addd( LDRH_IMM(temp2, data_reg, 1) ); // ldrh temp2, [data_reg, #1]
cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8
cache_addd( LDRB_IMM(temp2, data_reg, 3) ); // ldrb temp2, [data_reg, #3]
cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 24) ); // orr dest_reg, dest_reg, temp2, lsl #24
}
} else {
cache_addd( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg]
}
} else {
if ((Bit32u)data & 1) {
cache_addd( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg]
cache_addd( LDRB_IMM(temp2, data_reg, 1) ); // ldrb temp2, [data_reg, #1]
cache_addd( ORR_REG_LSL_IMM(dest_reg, dest_reg, temp2, 8) ); // orr dest_reg, dest_reg, temp2, lsl #8
} else {
cache_addd( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
}
}
}
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, temp1);
}
// move a 16bit constant value into dest_reg
// the upper 16bit of the destination register may be destroyed
static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
}
// helper function for gen_mov_word_from_reg
static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
// alignment....
if (dword) {
if ((Bit32u)dest & 3) {
if ( ((Bit32u)dest & 3) == 2 ) {
cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 16) ); // mov temp2, src_reg, lsr #16
cache_addd( STRH_IMM(temp2, data_reg, 2) ); // strh temp2, [data_reg, #2]
} else {
cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg]
cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8
cache_addd( STRH_IMM(temp2, data_reg, 1) ); // strh temp2, [data_reg, #1]
cache_addd( MOV_REG_LSR_IMM(temp2, temp2, 16) ); // mov temp2, temp2, lsr #16
cache_addd( STRB_IMM(temp2, data_reg, 3) ); // strb temp2, [data_reg, #3]
}
} else {
cache_addd( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg]
}
} else {
if ((Bit32u)dest & 1) {
cache_addd( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg]
cache_addd( MOV_REG_LSR_IMM(temp2, src_reg, 8) ); // mov temp2, src_reg, lsr #8
cache_addd( STRB_IMM(temp2, data_reg, 1) ); // strb temp2, [data_reg, #1]
} else {
cache_addd( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
}
}
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, temp1);
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
gen_mov_dword_to_reg_imm(temp1, (Bit32u)data);
cache_addd( LDRB_IMM(dest_reg, temp1, 0) ); // ldrb dest_reg, [temp1]
}
// move an 8bit value from memory into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void INLINE gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
gen_mov_byte_to_reg_low(dest_reg, data);
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
cache_addd( MOV_IMM(dest_reg, imm, 0) ); // mov dest_reg, #(imm)
}
// move an 8bit constant value into dest_reg
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
gen_mov_byte_to_reg_low_imm(dest_reg, imm);
}
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
cache_addd( STRB_IMM(src_reg, temp1, 0) ); // strb src_reg, [temp1]
}
// convert an 8bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_byte(bool sign,HostReg reg) {
if (sign) {
cache_addd( MOV_REG_LSL_IMM(reg, reg, 24) ); // mov reg, reg, lsl #24
cache_addd( MOV_REG_ASR_IMM(reg, reg, 24) ); // mov reg, reg, asr #24
} else {
cache_addd( AND_IMM(reg, reg, 0xff, 0) ); // and reg, reg, #0xff
}
}
// convert a 16bit word to a 32bit dword
// the register is zero-extended (sign==false) or sign-extended (sign==true)
static void gen_extend_word(bool sign,HostReg reg) {
if (sign) {
cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16
cache_addd( MOV_REG_ASR_IMM(reg, reg, 16) ); // mov reg, reg, asr #16
} else {
cache_addd( MOV_REG_LSL_IMM(reg, reg, 16) ); // mov reg, reg, lsl #16
cache_addd( MOV_REG_LSR_IMM(reg, reg, 16) ); // mov reg, reg, lsr #16
}
}
// add a 32bit value from memory to a full register
static void gen_add(HostReg reg,void* op) {
gen_mov_word_to_reg(temp3, op, 1);
cache_addd( ADD_REG_LSL_IMM(reg, reg, temp3, 0) ); // add reg, reg, temp3
}
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
Bits scale;
if(!imm) return;
if (imm == 0xffffffff) {
cache_addd( SUB_IMM(reg, reg, 1, 0) ); // sub reg, reg, #1
} else {
scale = 0;
while (imm) {
while ((imm & 3) == 0) {
imm>>=2;
scale+=2;
}
cache_addd( ADD_IMM(reg, reg, imm & 0xff, ROTATE_SCALE(scale)) ); // add reg, reg, #((imm & 0xff) << scale)
imm>>=8;
scale+=8;
}
}
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
Bits scale;
Bit32u imm2;
imm2 = ~imm;
if(!imm2) return;
if (!imm) {
cache_addd( MOV_IMM(reg, 0, 0) ); // mov reg, #0
} else {
scale = 0;
while (imm2) {
while ((imm2 & 3) == 0) {
imm2>>=2;
scale+=2;
}
cache_addd( BIC_IMM(reg, reg, imm2 & 0xff, ROTATE_SCALE(scale)) ); // bic reg, reg, #((imm2 & 0xff) << scale)
imm2>>=8;
scale+=8;
}
}
}
// move a 32bit constant value into memory
static void gen_mov_direct_dword(void* dest,Bit32u imm) {
gen_mov_dword_to_reg_imm(temp3, imm);
gen_mov_word_from_reg(temp3, dest, 1);
}
// move an address into memory
static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
gen_mov_word_to_reg_helper(temp3, dest, 1, temp1);
if (imm >= 0) {
cache_addd( ADD_IMM(temp3, temp3, (Bit32s)imm, 0) ); // add temp3, temp3, #(imm)
} else {
cache_addd( SUB_IMM(temp3, temp3, -((Bit32s)imm), 0) ); // sub temp3, temp3, #(-imm)
}
gen_mov_word_from_reg_helper(temp3, dest, 1, temp1);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
}
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
// maybe use function gen_add_imm
if (dword) {
gen_mov_dword_to_reg_imm(temp2, imm);
} else {
gen_mov_word_to_reg_imm(temp2, (Bit16u)imm);
}
cache_addd( ADD_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // add temp3, temp3, temp2
gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
gen_mov_word_to_reg_helper(temp3, dest, 1, temp1);
if (imm >= 0) {
cache_addd( SUB_IMM(temp3, temp3, (Bit32s)imm, 0) ); // sub temp3, temp3, #(imm)
} else {
cache_addd( ADD_IMM(temp3, temp3, -((Bit32s)imm), 0) ); // add temp3, temp3, #(-imm)
}
gen_mov_word_from_reg_helper(temp3, dest, 1, temp1);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
}
gen_mov_dword_to_reg_imm(temp1, (Bit32u)dest);
gen_mov_word_to_reg_helper(temp3, dest, dword, temp1);
// maybe use function gen_add_imm/gen_sub_imm
if (dword) {
gen_mov_dword_to_reg_imm(temp2, imm);
} else {
gen_mov_word_to_reg_imm(temp2, (Bit16u)imm);
}
cache_addd( SUB_REG_LSL_IMM(temp3, temp3, temp2, 0) ); // sub temp3, temp3, temp2
gen_mov_word_from_reg_helper(temp3, dest, dword, temp1);
}
// effective address calculation, destination is dest_reg
// scale_reg is scaled by scale (scale_reg*(2^scale)) and
// added to dest_reg, then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,HostReg scale_reg,Bitu scale,Bits imm) {
cache_addd( ADD_REG_LSL_IMM(dest_reg, dest_reg, scale_reg, scale) ); // add dest_reg, dest_reg, scale_reg, lsl #(scale)
gen_add_imm(dest_reg, imm);
}
// effective address calculation, destination is dest_reg
// dest_reg is scaled by scale (dest_reg*(2^scale)),
// then the immediate value is added
static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
if (scale) {
cache_addd( MOV_REG_LSL_IMM(dest_reg, dest_reg, scale) ); // mov dest_reg, dest_reg, lsl #(scale)
}
gen_add_imm(dest_reg, imm);
}
// generate a call to a parameterless function
static void INLINE gen_call_function_raw(void * func) {
cache_addd( LDR_IMM(temp1, HOST_pc, 4) ); // ldr temp1, [pc, #4]
cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4
cache_addd( BX(temp1) ); // bx temp1
cache_addd((Bit32u)func); // .int func
}
// generate a call to a function with paramcount parameters
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit32u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
Bit32u proc_addr = (Bit32u)cache.pos;
gen_call_function_raw(func);
return proc_addr;
}
#if (1)
// max of 4 parameters in a1-a4
// load an immediate value as param'th function parameter
static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
gen_mov_dword_to_reg_imm(param, imm);
}
// load an address as param'th function parameter
static void INLINE gen_load_param_addr(Bitu addr,Bitu param) {
gen_mov_dword_to_reg_imm(param, addr);
}
// load a host-register as param'th function parameter
static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
gen_mov_regs(param, reg);
}
// load a value from memory as param'th function parameter
static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
gen_mov_word_to_reg(param, (void *)mem, 1);
}
#else
other arm abis
#endif
// jump to an address pointed at by ptr, offset is in imm
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
Bits scale;
Bitu imm2;
gen_mov_word_to_reg(temp3, ptr, 1);
if (imm) {
scale = 0;
imm2 = (Bitu)imm;
while (imm2) {
while ((imm2 & 3) == 0) {
imm2>>=2;
scale+=2;
}
cache_addd( ADD_IMM(temp3, temp3, imm2 & 0xff, ROTATE_SCALE(scale)) ); // add temp3, temp3, #((imm2 & 0xff) << scale)
imm2>>=8;
scale+=8;
}
}
#if (1)
// (*ptr) should be word aligned
if ((imm & 0x03) == 0) {
cache_addd( LDR_IMM(temp1, temp3, 0) ); // ldr temp1, [temp3]
} else
#endif
{
cache_addd( LDRB_IMM(temp1, temp3, 0) ); // ldrb temp1, [temp3]
cache_addd( LDRB_IMM(temp2, temp3, 1) ); // ldrb temp2, [temp3, #1]
cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 8) ); // orr temp1, temp1, temp2, lsl #8
cache_addd( LDRB_IMM(temp2, temp3, 2) ); // ldrb temp2, [temp3, #2]
cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 16) ); // orr temp1, temp1, temp2, lsl #16
cache_addd( LDRB_IMM(temp2, temp3, 3) ); // ldrb temp2, [temp3, #3]
cache_addd( ORR_REG_LSL_IMM(temp1, temp1, temp2, 24) ); // orr temp1, temp1, temp2, lsl #24
}
cache_addd( BX(temp1) ); // bx temp1
}
// short conditional jump (+-127 bytes) if register is zero
// the destination is set by gen_fill_branch() later
static Bit32u gen_create_branch_on_zero(HostReg reg,bool dword) {
if (dword) {
cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0
} else {
cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16
}
cache_addd( BEQ_FWD(0) ); // beq j
return ((Bit32u)cache.pos-4);
}
// short conditional jump (+-127 bytes) if register is nonzero
// the destination is set by gen_fill_branch() later
static Bit32u gen_create_branch_on_nonzero(HostReg reg,bool dword) {
if (dword) {
cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0
} else {
cache_addd( MOVS_REG_LSL_IMM(temp1, reg, 16) ); // movs temp1, reg, lsl #16
}
cache_addd( BNE_FWD(0) ); // bne j
return ((Bit32u)cache.pos-4);
}
// calculate relative offset and fill it into the location pointed to by data
static void INLINE gen_fill_branch(DRC_PTR_SIZE_IM data) {
#if C_DEBUG
Bits len=(Bit32u)cache.pos-(data+8);
if (len<0) len=-len;
if (len>0x02000000) LOG_MSG("Big jump %d",len);
#endif
*(Bit32u*)data=( (*(Bit32u*)data) & 0xff000000 ) | ( ( ((Bit32u)cache.pos - (data+8)) >> 2 ) & 0x00ffffff );
}
// conditional jump if register is nonzero
// for isdword==true the 32bit of the register are tested
// for isdword==false the lowest 8bit of the register are tested
static Bit32u gen_create_branch_long_nonzero(HostReg reg,bool isdword) {
if (isdword) {
cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0
} else {
cache_addd( TST_IMM(reg, 0xff, 0) ); // tst reg, #0xff
}
cache_addd( BEQ_FWD(8) ); // beq nobranch (pc +8)
cache_addd( LDR_IMM(temp1, HOST_pc, 0) ); // ldr temp1, [pc, #0]
cache_addd( BX(temp1) ); // bx temp1
cache_addd(0); // fill j
// nobranch:
return ((Bit32u)cache.pos-4);
}
// compare 32bit-register against zero and jump if value less/equal than zero
static Bit32u gen_create_branch_long_leqzero(HostReg reg) {
cache_addd( CMP_IMM(reg, 0, 0) ); // cmp reg, #0
cache_addd( BGT_FWD(8) ); // bgt nobranch (pc+8)
cache_addd( LDR_IMM(temp1, HOST_pc, 0) ); // ldr temp1, [pc, #0]
cache_addd( BX(temp1) ); // bx temp1
cache_addd(0); // fill j
// nobranch:
return ((Bit32u)cache.pos-4);
}
// calculate long relative offset and fill it into the location pointed to by data
static void INLINE gen_fill_branch_long(Bit32u data) {
// this is an absolute branch
*(Bit32u*)data=(Bit32u)cache.pos;
}
static void gen_run_code(void) {
cache_addd(0xe92d4000); // stmfd sp!, {lr}
cache_addd(0xe92d0cf0); // stmfd sp!, {v1-v4,v7,v8}
// adr: 8
cache_addd( LDR_IMM(FC_SEGS_ADDR, HOST_pc, 64 - (8 + 8)) ); // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
// adr: 12
cache_addd( LDR_IMM(FC_REGS_ADDR, HOST_pc, 68 - (12 + 8)) ); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
cache_addd( ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4
cache_addd(0xe92d4000); // stmfd sp!, {lr}
cache_addd( BX(HOST_r0) ); // bx r0
cache_addd(0xe8bd0cf0); // ldmfd sp!, {v1-v4,v7,v8}
cache_addd(0xe8bd4000); // ldmfd sp!, {lr}
cache_addd( BX(HOST_lr) ); // bx lr
// fill up to 64 bytes
cache_addd( NOP ); // nop
cache_addd( NOP ); // nop
cache_addd( NOP ); // nop
cache_addd( NOP ); // nop
cache_addd( NOP ); // nop
cache_addd( NOP ); // nop
// adr: 64
cache_addd((Bit32u)&Segs); // address of "Segs"
// adr: 68
cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs"
}
// return from a function
static void gen_return_function(void) {
cache_addd(0xe8bd4000); // ldmfd sp!, {lr}
cache_addd( BX(HOST_lr) ); // bx lr
}
#ifdef DRC_FLAGS_INVALIDATION
// called when a call to a function can be replaced by a
// call to a simpler function
static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
#ifdef DRC_FLAGS_INVALIDATION_DCODE
// try to avoid function calls but rather directly fill in code
switch (flags_type) {
case t_ADDb:
case t_ADDw:
case t_ADDd:
*(Bit32u*)pos=ADD_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // add FC_RETOP, a1, a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_ORb:
case t_ORw:
case t_ORd:
*(Bit32u*)pos=ORR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // orr FC_RETOP, a1, a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_ANDb:
case t_ANDw:
case t_ANDd:
*(Bit32u*)pos=AND_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // and FC_RETOP, a1, a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SUBb:
case t_SUBw:
case t_SUBd:
*(Bit32u*)pos=SUB_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // sub FC_RETOP, a1, a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_XORb:
case t_XORw:
case t_XORd:
*(Bit32u*)pos=EOR_REG_LSL_IMM(FC_RETOP, HOST_a1, HOST_a2, 0); // eor FC_RETOP, a1, a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_CMPb:
case t_CMPw:
case t_CMPd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
*(Bit32u*)pos=B_FWD(8); // b (pc+2*4)
break;
case t_INCb:
case t_INCw:
case t_INCd:
*(Bit32u*)pos=ADD_IMM(FC_RETOP, HOST_a1, 1, 0); // add FC_RETOP, a1, #1
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_DECb:
case t_DECw:
case t_DECd:
*(Bit32u*)pos=SUB_IMM(FC_RETOP, HOST_a1, 1, 0); // sub FC_RETOP, a1, #1
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SHLb:
case t_SHLw:
case t_SHLd:
*(Bit32u*)pos=MOV_REG_LSL_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsl a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SHRb:
*(Bit32u*)pos=AND_IMM(FC_RETOP, HOST_a1, 0xff, 0); // and FC_RETOP, a1, #0xff
*(Bit32u*)(pos+4)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SHRw:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16
*(Bit32u*)(pos+4)=MOV_REG_LSR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, lsr #16
*(Bit32u*)(pos+8)=MOV_REG_LSR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, lsr a2
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SHRd:
*(Bit32u*)pos=MOV_REG_LSR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, lsr a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SARb:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24
*(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 24); // mov FC_RETOP, FC_RETOP, asr #24
*(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SARw:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16
*(Bit32u*)(pos+4)=MOV_REG_ASR_IMM(FC_RETOP, FC_RETOP, 16); // mov FC_RETOP, FC_RETOP, asr #16
*(Bit32u*)(pos+8)=MOV_REG_ASR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, asr a2
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_SARd:
*(Bit32u*)pos=MOV_REG_ASR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, asr a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_RORb:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 24); // mov FC_RETOP, a1, lsl #24
*(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 8); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #8
*(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
*(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2
break;
case t_RORw:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16
*(Bit32u*)(pos+4)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
*(Bit32u*)(pos+8)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_RORd:
*(Bit32u*)pos=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_ROLw:
*(Bit32u*)pos=MOV_REG_LSL_IMM(FC_RETOP, HOST_a1, 16); // mov FC_RETOP, a1, lsl #16
*(Bit32u*)(pos+4)=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32
*(Bit32u*)(pos+8)=ORR_REG_LSR_IMM(FC_RETOP, FC_RETOP, FC_RETOP, 16); // orr FC_RETOP, FC_RETOP, FC_RETOP, lsr #16
*(Bit32u*)(pos+12)=MOV_REG_ROR_REG(FC_RETOP, FC_RETOP, HOST_a2); // mov FC_RETOP, FC_RETOP, ror a2
break;
case t_ROLd:
*(Bit32u*)pos=RSB_IMM(HOST_a2, HOST_a2, 32, 0); // rsb a2, a2, #32
*(Bit32u*)(pos+4)=MOV_REG_ROR_REG(FC_RETOP, HOST_a1, HOST_a2); // mov FC_RETOP, a1, ror a2
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
case t_NEGb:
case t_NEGw:
case t_NEGd:
*(Bit32u*)pos=RSB_IMM(FC_RETOP, HOST_a1, 0, 0); // rsb FC_RETOP, a1, #0
*(Bit32u*)(pos+4)=NOP; // nop
*(Bit32u*)(pos+8)=NOP; // nop
*(Bit32u*)(pos+12)=NOP; // nop
break;
default:
*(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func
break;
}
#else
*(Bit32u*)(pos+12)=(Bit32u)fct_ptr; // simple_func
#endif
}
#endif
static void cache_block_before_close(void) { }
#ifdef DRC_USE_SEGS_ADDR
// mov 16bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 2 must be zero)
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_seg16_to_reg(HostReg dest_reg,Bitu index) {
cache_addd( LDRH_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldrh dest_reg, [FC_SEGS_ADDR, #index]
}
// mov 32bit value from Segs[index] into dest_reg using FC_SEGS_ADDR (index modulo 4 must be zero)
static void gen_mov_seg32_to_reg(HostReg dest_reg,Bitu index) {
cache_addd( LDR_IMM(dest_reg, FC_SEGS_ADDR, index) ); // ldr dest_reg, [FC_SEGS_ADDR, #index]
}
// add a 32bit value from Segs[index] to a full register using FC_SEGS_ADDR (index modulo 4 must be zero)
static void gen_add_seg32_to_reg(HostReg reg,Bitu index) {
cache_addd( LDR_IMM(temp1, FC_SEGS_ADDR, index) ); // ldr temp1, [FC_SEGS_ADDR, #index]
cache_addd( ADD_REG_LSL_IMM(reg, reg, temp1, 0) ); // add reg, reg, temp1
}
#endif
#ifdef DRC_USE_REGS_ADDR
// mov 16bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 2 must be zero)
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_regval16_to_reg(HostReg dest_reg,Bitu index) {
cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index]
}
// mov 32bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (index modulo 4 must be zero)
static void gen_mov_regval32_to_reg(HostReg dest_reg,Bitu index) {
cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index]
}
// move a 32bit (dword==true) or 16bit (dword==false) value from cpu_regs[index] into dest_reg using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_regword_to_reg(HostReg dest_reg,Bitu index,bool dword) {
if (dword) {
cache_addd( LDR_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldr dest_reg, [FC_REGS_ADDR, #index]
} else {
cache_addd( LDRH_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrh dest_reg, [FC_REGS_ADDR, #index]
}
}
// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR
// the upper 24bit of the destination register can be destroyed
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_regbyte_to_reg_low(HostReg dest_reg,Bitu index) {
cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index]
}
// move an 8bit value from cpu_regs[index] into dest_reg using FC_REGS_ADDR
// the upper 24bit of the destination register can be destroyed
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void INLINE gen_mov_regbyte_to_reg_low_canuseword(HostReg dest_reg,Bitu index) {
cache_addd( LDRB_IMM(dest_reg, FC_REGS_ADDR, index) ); // ldrb dest_reg, [FC_REGS_ADDR, #index]
}
// add a 32bit value from cpu_regs[index] to a full register using FC_REGS_ADDR (index modulo 4 must be zero)
static void gen_add_regval32_to_reg(HostReg reg,Bitu index) {
cache_addd( LDR_IMM(temp2, FC_REGS_ADDR, index) ); // ldr temp2, [FC_REGS_ADDR, #index]
cache_addd( ADD_REG_LSL_IMM(reg, reg, temp2, 0) ); // add reg, reg, temp2
}
// move 16bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 2 must be zero)
static void gen_mov_regval16_from_reg(HostReg src_reg,Bitu index) {
cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index]
}
// move 32bit of register into cpu_regs[index] using FC_REGS_ADDR (index modulo 4 must be zero)
static void gen_mov_regval32_from_reg(HostReg src_reg,Bitu index) {
cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index]
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into cpu_regs[index] using FC_REGS_ADDR (if dword==true index modulo 4 must be zero) (if dword==false index modulo 2 must be zero)
static void gen_mov_regword_from_reg(HostReg src_reg,Bitu index,bool dword) {
if (dword) {
cache_addd( STR_IMM(src_reg, FC_REGS_ADDR, index) ); // str src_reg, [FC_REGS_ADDR, #index]
} else {
cache_addd( STRH_IMM(src_reg, FC_REGS_ADDR, index) ); // strh src_reg, [FC_REGS_ADDR, #index]
}
}
// move the lowest 8bit of a register into cpu_regs[index] using FC_REGS_ADDR
static void gen_mov_regbyte_from_reg_low(HostReg src_reg,Bitu index) {
cache_addd( STRB_IMM(src_reg, FC_REGS_ADDR, index) ); // strb src_reg, [FC_REGS_ADDR, #index]
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -50,15 +50,14 @@
// temporary register for LEA
#define TEMP_REG_DRC HOST_a4
#ifdef DRC_USE_REGS_ADDR
// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
#define FC_REGS_ADDR HOST_v7
#endif
#ifdef DRC_USE_SEGS_ADDR
// used to hold the address of "Segs" - preferably filled in function gen_run_code
#define FC_SEGS_ADDR HOST_v8
#endif
// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
#define readdata_addr HOST_v5
// instruction encodings
@ -98,10 +97,14 @@
// logical
// and dst, src
#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
// bic dst, src
#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
// eor dst, src
#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
// orr dst, src
#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
// mvn dst, src
#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
// shift/rotate
// lsl dst, src, #imm
@ -128,6 +131,8 @@
#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0
#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
// ldr reg, [addr1, addr2]
#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
// store
// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0
@ -150,6 +155,25 @@
#define BX(reg) (0x4700 + ((reg) << 3) )
// arm instructions
// arithmetic
// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// load
// ldr reg, [addr, #imm] @ 0 <= imm < 4096
#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// store
// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096
#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// branch
// bx reg
#define ARM_BX(reg) (0xe12fff10 + (reg) )
// data pool defines
#define CACHE_DATA_JUMP (2)
#define CACHE_DATA_ALIGN (32)
@ -193,7 +217,7 @@ static void cache_checkinstr(Bit32u size) {
cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
} else {
register Bit32u cachemodsize;
cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
@ -275,30 +299,49 @@ static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src
}
// helper function
static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
Bit32u shift;
if (GCC_UNLIKELY(value == 0)) {
*val_shift = 0;
return true;
}
shift = 0;
while ((value & 1) == 0) {
value>>=1;
shift+=1;
}
if ((value >> 8) != 0) return false;
*val_shift = shift;
return true;
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
if ((imm & 0xffffff00) == 0) {
Bit32u scale;
if (imm < 256) {
cache_checkinstr(2);
cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm)
} else if ((imm & 0xffff00ff) == 0) {
} else if ((~imm) < 256) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 8) ); // mov dest_reg, #(imm >> 8)
cache_addw( LSL_IMM(dest_reg, dest_reg, 8) ); // lsl dest_reg, dest_reg, #8
} else if ((imm & 0xff00ffff) == 0) {
cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm)
cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg
} else if (val_single_shift(imm, &scale)) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 16) ); // mov dest_reg, #(imm >> 16)
cache_addw( LSL_IMM(dest_reg, dest_reg, 16) ); // lsl dest_reg, dest_reg, #16
} else if ((imm & 0x00ffffff) == 0) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 24) ); // mov dest_reg, #(imm >> 24)
cache_addw( LSL_IMM(dest_reg, dest_reg, 24) ); // lsl dest_reg, dest_reg, #24
cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale)
cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale
} else {
Bit32u diff;
cache_checkinstr(4);
diff = imm - ((Bit32u)cache.pos+4);
if ((diff < 1024) && ((imm & 0x03) == 0)) {
if (((Bit32u)cache.pos & 0x03) == 0) {
cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) ); // add dest_reg, pc, #(diff >> 2)
@ -321,10 +364,61 @@ static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
}
}
// helper function
static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_to_reg
static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 3) {
if ( ((Bit32u)data & 3) == 2 ) {
cache_checkinstr(8);
@ -343,18 +437,23 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
}
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 1) {
cache_checkinstr(8);
cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg]
cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1]
cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
}
@ -364,8 +463,10 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
}
}
// move a 16bit constant value into dest_reg
@ -374,10 +475,61 @@ static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
}
// helper function
static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_from_reg
static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 3) {
if ( ((Bit32u)dest & 3) == 2 ) {
cache_checkinstr(8);
@ -398,18 +550,23 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24
cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3]
}
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 1) {
cache_checkinstr(8);
cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg]
cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg
cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8
cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1]
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
}
@ -418,8 +575,10 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
}
}
// move an 8bit value from memory into dest_reg
@ -427,9 +586,11 @@ static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_checkinstr(2);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_checkinstr(2);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
}
}
// move an 8bit value from memory into dest_reg
@ -459,9 +620,11 @@ static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_checkinstr(2);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_checkinstr(2);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
}
}
@ -501,18 +664,58 @@ static void gen_add(HostReg reg,void* op) {
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
Bit32u imm2, scale;
if(!imm) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_checkinstr(2);
cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm
} else if (imm2 <= 255) {
cache_checkinstr(2);
cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm)
} else {
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
}
}
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
if(imm == 0xffffffff) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( AND(reg, templo1) ); // and reg, templo1
Bit32u imm2, scale;
imm2 = ~imm;
if(!imm2) return;
if (!imm) {
cache_checkinstr(2);
cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0
} else {
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( BIC(reg, templo1) ); // bic reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( AND(reg, templo1) ); // and reg, templo1
}
}
}
@ -527,70 +730,69 @@ static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
cache_checkinstr(2);
if (imm >= 0) {
cache_addw( ADD_IMM8(templo3, (Bit32s)imm) ); // add templo3, #(imm)
} else {
cache_addw( SUB_IMM8(templo3, -((Bit32s)imm)) ); // sub templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
gen_add_imm(templo3, imm);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
cache_checkinstr(2);
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
cache_checkinstr(2);
if (imm >= 0) {
cache_addw( SUB_IMM8(templo3, (Bit32s)imm) ); // sub templo3, #(imm)
} else {
cache_addw( ADD_IMM8(templo3, -((Bit32s)imm)) ); // add templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
gen_add_direct_word(dest, (Bit32s)imm, 1);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
Bit32u imm2, scale;
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_checkinstr(2);
cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm
} else if (imm2 <= 255) {
cache_checkinstr(2);
cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm)
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
}
}
cache_checkinstr(2);
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
gen_sub_direct_word(dest, (Bit32s)imm, 1);
}
// effective address calculation, destination is dest_reg
@ -694,20 +896,22 @@ static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
gen_mov_word_to_reg(templo3, ptr, 1);
if (imm) {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(templo3, templo3, templo2) ); // add templo3, templo3, templo2
}
#if (1)
// (*ptr) should be word aligned
#if !defined(C_UNALIGNED_MEMORY)
// (*ptr) should be word aligned
if ((imm & 0x03) == 0) {
cache_checkinstr(6);
cache_addw( LDR_IMM(templo2, templo3, 0) ); // ldr templo2, [templo3]
} else
#endif
{
if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
cache_checkinstr(6);
cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm]
} else {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_checkinstr(6);
cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2]
}
#if !defined(C_UNALIGNED_MEMORY)
} else {
gen_add_imm(templo3, imm);
cache_checkinstr(24);
cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3]
cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1]
@ -720,6 +924,7 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) {
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1
}
#endif
// increase jmp address to keep thumb state
cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1
@ -815,50 +1020,53 @@ static void INLINE gen_fill_branch_long(Bit32u data) {
}
static void gen_run_code(void) {
// switch from arm to thumb state
cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1
cache_addd(0xe12fff10 + (HOST_r3)); // bx r3
Bit8u *pos1, *pos2, *pos3;
// thumb state from now on
cache_addw(0xb500); // push {lr}
cache_addw( MOV_LO_HI(HOST_r3, FC_SEGS_ADDR) ); // mov r3, FC_SEGS_ADDR
cache_addw( MOV_LO_HI(HOST_r2, FC_REGS_ADDR) ); // mov r2, FC_REGS_ADDR
cache_addw(0xb4fc); // push {r2,r3,v1-v4}
#if (__ARM_EABI__)
// 8-byte stack alignment
cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr}
#endif
// adr: 16
cache_addw( LDR_PC_IMM(HOST_r3, 64 - (16 + 4)) ); // ldr r3, [pc, #(&Segs)]
// adr: 18
cache_addw( LDR_PC_IMM(HOST_r2, 68 - (18 + 2)) ); // ldr r2, [pc, #(&cpu_regs)]
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1
// align 4
cache_addw( ADD_LO_PC_IMM(HOST_r3, 8) ); // add r3, pc, #8
cache_addw( ADD_IMM8(HOST_r0, 1) ); // add r0, #1
cache_addw( ADD_IMM8(HOST_r3, 1) ); // add r3, #1
cache_addw(0xb408); // push {r3}
cache_addw( BX(HOST_r0) ); // bx r0
cache_addw( NOP ); // nop
pos1 = cache.pos;
cache_addd( 0 );
pos2 = cache.pos;
cache_addd( 0 );
pos3 = cache.pos;
cache_addd( 0 );
// align 4
cache_addw(0xbcfc); // pop {r2,r3,v1-v4}
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4
cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]!
cache_addd( ARM_BX(HOST_r0) ); // bx r0
cache_addw(0xbc08); // pop {r3}
cache_addw( BX(HOST_r3) ); // bx r3
#if (__ARM_EABI__)
cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr}
#endif
cache_addd( ARM_BX(HOST_lr) ); // bx lr
// fill up to 64 bytes
cache_addw( NOP ); // nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
// adr: 64
*(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
cache_addd((Bit32u)&Segs); // address of "Segs"
// adr: 68
*(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs"
*(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata"
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
}
// return from a function

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -50,15 +50,14 @@
// temporary register for LEA
#define TEMP_REG_DRC HOST_a4
#ifdef DRC_USE_REGS_ADDR
// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
#define FC_REGS_ADDR HOST_v7
#endif
#ifdef DRC_USE_SEGS_ADDR
// used to hold the address of "Segs" - preferably filled in function gen_run_code
#define FC_SEGS_ADDR HOST_v8
#endif
// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
#define readdata_addr HOST_v5
// instruction encodings
@ -98,10 +97,14 @@
// logical
// and dst, src
#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
// bic dst, src
#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
// eor dst, src
#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
// orr dst, src
#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
// mvn dst, src
#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
// shift/rotate
// lsl dst, src, #imm
@ -128,6 +131,8 @@
#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0
#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
// ldr reg, [addr1, addr2]
#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
// store
// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0
@ -150,6 +155,25 @@
#define BX(reg) (0x4700 + ((reg) << 3) )
// arm instructions
// arithmetic
// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// load
// ldr reg, [addr, #imm] @ 0 <= imm < 4096
#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// store
// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096
#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// branch
// bx reg
#define ARM_BX(reg) (0xe12fff10 + (reg) )
// data pool defines
#define CACHE_DATA_JUMP (2)
#define CACHE_DATA_ALIGN (32)
@ -193,7 +217,7 @@ static void cache_checkinstr(Bit32u size) {
cache_datapos = (Bit8u *) (((Bitu)cache.block.active->cache.start + cache.block.active->cache.size - CACHE_DATA_ALIGN) & ~(CACHE_DATA_ALIGN - 1));
} else {
register Bit32u cachemodsize;
cachemodsize = (cache.pos - cache.block.active->cache.start) & (CACHE_MAXSIZE - 1);
if (cachemodsize + CACHE_DATA_MAX + CACHE_DATA_ALIGN <= CACHE_MAXSIZE ||
@ -275,30 +299,49 @@ static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src
}
// helper function
static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
Bit32u shift;
if (GCC_UNLIKELY(value == 0)) {
*val_shift = 0;
return true;
}
shift = 0;
while ((value & 1) == 0) {
value>>=1;
shift+=1;
}
if ((value >> 8) != 0) return false;
*val_shift = shift;
return true;
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
if ((imm & 0xffffff00) == 0) {
Bit32u scale;
if (imm < 256) {
cache_checkinstr(2);
cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm)
} else if ((imm & 0xffff00ff) == 0) {
} else if ((~imm) < 256) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 8) ); // mov dest_reg, #(imm >> 8)
cache_addw( LSL_IMM(dest_reg, dest_reg, 8) ); // lsl dest_reg, dest_reg, #8
} else if ((imm & 0xff00ffff) == 0) {
cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm)
cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg
} else if (val_single_shift(imm, &scale)) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 16) ); // mov dest_reg, #(imm >> 16)
cache_addw( LSL_IMM(dest_reg, dest_reg, 16) ); // lsl dest_reg, dest_reg, #16
} else if ((imm & 0x00ffffff) == 0) {
cache_checkinstr(4);
cache_addw( MOV_IMM(dest_reg, imm >> 24) ); // mov dest_reg, #(imm >> 24)
cache_addw( LSL_IMM(dest_reg, dest_reg, 24) ); // lsl dest_reg, dest_reg, #24
cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale)
cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale
} else {
Bit32u diff;
cache_checkinstr(4);
diff = imm - ((Bit32u)cache.pos+4);
if ((diff < 1024) && ((imm & 0x03) == 0)) {
if (((Bit32u)cache.pos & 0x03) == 0) {
cache_addw( ADD_LO_PC_IMM(dest_reg, diff >> 2) ); // add dest_reg, pc, #(diff >> 2)
@ -321,10 +364,61 @@ static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
}
}
// helper function
static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_to_reg
static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 3) {
if ( ((Bit32u)data & 3) == 2 ) {
cache_checkinstr(8);
@ -343,18 +437,23 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
}
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 1) {
cache_checkinstr(8);
cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg]
cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1]
cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
}
@ -364,8 +463,10 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
}
}
// move a 16bit constant value into dest_reg
@ -374,10 +475,61 @@ static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
}
// helper function
static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_checkinstr(4);
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_from_reg
static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 3) {
if ( ((Bit32u)dest & 3) == 2 ) {
cache_checkinstr(8);
@ -398,18 +550,23 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24
cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3]
}
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 1) {
cache_checkinstr(8);
cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg]
cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg
cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8
cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1]
} else {
} else
#endif
{
cache_checkinstr(2);
cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
}
@ -418,8 +575,10 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
}
}
// move an 8bit value from memory into dest_reg
@ -427,9 +586,11 @@ static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_checkinstr(2);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_checkinstr(2);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
}
}
// move an 8bit value from memory into dest_reg
@ -459,9 +620,11 @@ static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_checkinstr(2);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_checkinstr(2);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
}
}
@ -501,18 +664,58 @@ static void gen_add(HostReg reg,void* op) {
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
Bit32u imm2, scale;
if(!imm) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_checkinstr(2);
cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm
} else if (imm2 <= 255) {
cache_checkinstr(2);
cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm)
} else {
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
}
}
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
if(imm == 0xffffffff) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( AND(reg, templo1) ); // and reg, templo1
Bit32u imm2, scale;
imm2 = ~imm;
if(!imm2) return;
if (!imm) {
cache_checkinstr(2);
cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0
} else {
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( BIC(reg, templo1) ); // bic reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( AND(reg, templo1) ); // and reg, templo1
}
}
}
@ -527,70 +730,69 @@ static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
cache_checkinstr(2);
if (imm >= 0) {
cache_addw( ADD_IMM8(templo3, (Bit32s)imm) ); // add templo3, #(imm)
} else {
cache_addw( SUB_IMM8(templo3, -((Bit32s)imm)) ); // sub templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
gen_add_imm(templo3, imm);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
cache_checkinstr(2);
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
cache_checkinstr(2);
if (imm >= 0) {
cache_addw( SUB_IMM8(templo3, (Bit32s)imm) ); // sub templo3, #(imm)
} else {
cache_addw( ADD_IMM8(templo3, -((Bit32s)imm)) ); // add templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
gen_add_direct_word(dest, (Bit32s)imm, 1);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
Bit32u imm2, scale;
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_checkinstr(2);
cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm
} else if (imm2 <= 255) {
cache_checkinstr(2);
cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm)
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
if (val_single_shift(imm2, &scale)) {
cache_checkinstr((scale)?6:4);
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_checkinstr(2);
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
}
}
cache_checkinstr(2);
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
gen_sub_direct_word(dest, (Bit32s)imm, 1);
}
// effective address calculation, destination is dest_reg
@ -696,20 +898,22 @@ static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
gen_mov_word_to_reg(templo3, ptr, 1);
if (imm) {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_checkinstr(2);
cache_addw( ADD_REG(templo3, templo3, templo2) ); // add templo3, templo3, templo2
}
#if (1)
// (*ptr) should be word aligned
#if !defined(C_UNALIGNED_MEMORY)
// (*ptr) should be word aligned
if ((imm & 0x03) == 0) {
cache_checkinstr(6);
cache_addw( LDR_IMM(templo2, templo3, 0) ); // ldr templo2, [templo3]
} else
#endif
{
if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
cache_checkinstr(6);
cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm]
} else {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_checkinstr(6);
cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2]
}
#if !defined(C_UNALIGNED_MEMORY)
} else {
gen_add_imm(templo3, imm);
cache_checkinstr(24);
cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3]
cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1]
@ -722,6 +926,7 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) {
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1
}
#endif
// increase jmp address to keep thumb state
cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1
@ -817,50 +1022,53 @@ static void INLINE gen_fill_branch_long(Bit32u data) {
}
static void gen_run_code(void) {
// switch from arm to thumb state
cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1
cache_addd(0xe12fff10 + (HOST_r3)); // bx r3
Bit8u *pos1, *pos2, *pos3;
// thumb state from now on
cache_addw(0xb500); // push {lr}
cache_addw( MOV_LO_HI(HOST_r3, FC_SEGS_ADDR) ); // mov r3, FC_SEGS_ADDR
cache_addw( MOV_LO_HI(HOST_r2, FC_REGS_ADDR) ); // mov r2, FC_REGS_ADDR
cache_addw(0xb4fc); // push {r2,r3,v1-v4}
#if (__ARM_EABI__)
// 8-byte stack alignment
cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr}
#endif
// adr: 16
cache_addw( LDR_PC_IMM(HOST_r3, 64 - (16 + 4)) ); // ldr r3, [pc, #(&Segs)]
// adr: 18
cache_addw( LDR_PC_IMM(HOST_r2, 68 - (18 + 2)) ); // ldr r2, [pc, #(&cpu_regs)]
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1
// align 4
cache_addw( ADD_LO_PC_IMM(HOST_r3, 8) ); // add r3, pc, #8
cache_addw( ADD_IMM8(HOST_r0, 1) ); // add r0, #1
cache_addw( ADD_IMM8(HOST_r3, 1) ); // add r3, #1
cache_addw(0xb408); // push {r3}
cache_addw( BX(HOST_r0) ); // bx r0
cache_addw( NOP ); // nop
pos1 = cache.pos;
cache_addd( 0 );
pos2 = cache.pos;
cache_addd( 0 );
pos3 = cache.pos;
cache_addd( 0 );
// align 4
cache_addw(0xbcfc); // pop {r2,r3,v1-v4}
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4
cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]!
cache_addd( ARM_BX(HOST_r0) ); // bx r0
cache_addw(0xbc08); // pop {r3}
cache_addw( BX(HOST_r3) ); // bx r3
#if (__ARM_EABI__)
cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr}
#endif
cache_addd( ARM_BX(HOST_lr) ); // bx lr
// fill up to 64 bytes
cache_addw( NOP ); // nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
// adr: 64
*(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
cache_addd((Bit32u)&Segs); // address of "Segs"
// adr: 68
*(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs"
*(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata"
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
}
// return from a function

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -50,15 +50,14 @@
// temporary register for LEA
#define TEMP_REG_DRC HOST_a4
#ifdef DRC_USE_REGS_ADDR
// used to hold the address of "cpu_regs" - preferably filled in function gen_run_code
#define FC_REGS_ADDR HOST_v7
#endif
#ifdef DRC_USE_SEGS_ADDR
// used to hold the address of "Segs" - preferably filled in function gen_run_code
#define FC_SEGS_ADDR HOST_v8
#endif
// used to hold the address of "core_dynrec.readdata" - filled in function gen_run_code
#define readdata_addr HOST_v5
// instruction encodings
@ -98,10 +97,14 @@
// logical
// and dst, src
#define AND(dst, src) (0x4000 + (dst) + ((src) << 3) )
// bic dst, src
#define BIC(dst, src) (0x4380 + (dst) + ((src) << 3) )
// eor dst, src
#define EOR(dst, src) (0x4040 + (dst) + ((src) << 3) )
// orr dst, src
#define ORR(dst, src) (0x4300 + (dst) + ((src) << 3) )
// mvn dst, src
#define MVN(dst, src) (0x43c0 + (dst) + ((src) << 3) )
// shift/rotate
// lsl dst, src, #imm
@ -128,6 +131,8 @@
#define LDRB_IMM(reg, addr, imm) (0x7800 + (reg) + ((addr) << 3) + ((imm) << 6) )
// ldr reg, [pc, #imm] @ 0 <= imm < 1024 & imm mod 4 = 0
#define LDR_PC_IMM(reg, imm) (0x4800 + ((reg) << 8) + ((imm) >> 2) )
// ldr reg, [addr1, addr2]
#define LDR_REG(reg, addr1, addr2) (0x5800 + (reg) + ((addr1) << 3) + ((addr2) << 6) )
// store
// str reg, [addr, #imm] @ 0 <= imm < 128 & imm mod 4 = 0
@ -150,30 +155,69 @@
#define BX(reg) (0x4700 + ((reg) << 3) )
// arm instructions
// arithmetic
// add dst, src, #(imm ror rimm) @ 0 <= imm <= 255 & rimm mod 2 = 0
#define ARM_ADD_IMM(dst, src, imm, rimm) (0xe2800000 + ((dst) << 12) + ((src) << 16) + (imm) + ((rimm) << 7) )
// load
// ldr reg, [addr, #imm] @ 0 <= imm < 4096
#define ARM_LDR_IMM(reg, addr, imm) (0xe5900000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// store
// str reg, [addr, #-(imm)]! @ 0 <= imm < 4096
#define ARM_STR_IMM_M_W(reg, addr, imm) (0xe5200000 + ((reg) << 12) + ((addr) << 16) + (imm) )
// branch
// bx reg
#define ARM_BX(reg) (0xe12fff10 + (reg) )
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
if(reg_src == reg_dst) return;
cache_addw( MOV_REG(reg_dst, reg_src) ); // mov reg_dst, reg_src
}
// helper function
static bool val_single_shift(Bit32u value, Bit32u *val_shift) {
Bit32u shift;
if (GCC_UNLIKELY(value == 0)) {
*val_shift = 0;
return true;
}
shift = 0;
while ((value & 1) == 0) {
value>>=1;
shift+=1;
}
if ((value >> 8) != 0) return false;
*val_shift = shift;
return true;
}
// move a 32bit constant value into dest_reg
static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
if ((imm & 0xffffff00) == 0) {
cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #(imm)
} else if ((imm & 0xffff00ff) == 0) {
cache_addw( MOV_IMM(dest_reg, imm >> 8) ); // mov dest_reg, #(imm >> 8)
cache_addw( LSL_IMM(dest_reg, dest_reg, 8) ); // lsl dest_reg, dest_reg, #8
} else if ((imm & 0xff00ffff) == 0) {
cache_addw( MOV_IMM(dest_reg, imm >> 16) ); // mov dest_reg, #(imm >> 16)
cache_addw( LSL_IMM(dest_reg, dest_reg, 16) ); // lsl dest_reg, dest_reg, #16
} else if ((imm & 0x00ffffff) == 0) {
cache_addw( MOV_IMM(dest_reg, imm >> 24) ); // mov dest_reg, #(imm >> 24)
cache_addw( LSL_IMM(dest_reg, dest_reg, 24) ); // lsl dest_reg, dest_reg, #24
Bit32u scale;
if (imm < 256) {
cache_addw( MOV_IMM(dest_reg, imm) ); // mov dest_reg, #imm
} else if ((~imm) < 256) {
cache_addw( MOV_IMM(dest_reg, ~imm) ); // mov dest_reg, #(~imm)
cache_addw( MVN(dest_reg, dest_reg) ); // mvn dest_reg, dest_reg
} else if (val_single_shift(imm, &scale)) {
cache_addw( MOV_IMM(dest_reg, imm >> scale) ); // mov dest_reg, #(imm >> scale)
cache_addw( LSL_IMM(dest_reg, dest_reg, scale) ); // lsl dest_reg, dest_reg, #scale
} else {
Bit32u diff;
diff = imm - ((Bit32u)cache.pos+4);
if ((diff < 1024) && ((imm & 0x03) == 0)) {
if (((Bit32u)cache.pos & 0x03) == 0) {
cache_addw( ADD_LO_PC_IMM(dest_reg, diff) ); // add dest_reg, pc, #(diff >> 2)
@ -198,10 +242,58 @@ static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
}
}
// helper function
static bool gen_mov_memval_to_reg_helper(HostReg dest_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDR_IMM(dest_reg, templo2, data - addr_data) ); // ldr dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRH_IMM(dest_reg, templo2, data - addr_data) ); // ldrh dest_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( LDRB_IMM(dest_reg, templo2, data - addr_data) ); // ldrb dest_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_to_reg(HostReg dest_reg, void *data, Bitu size) {
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_to_reg_helper(dest_reg, (Bit32u)data, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_to_reg
static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 3) {
if ( ((Bit32u)data & 3) == 2 ) {
cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
@ -218,16 +310,21 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
}
} else {
} else
#endif
{
cache_addw( LDR_IMM(dest_reg, data_reg, 0) ); // ldr dest_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)data & 1) {
cache_addw( LDRB_IMM(dest_reg, data_reg, 0) ); // ldrb dest_reg, [data_reg]
cache_addw( LDRB_IMM(templo1, data_reg, 1) ); // ldrb templo1, [data_reg, #1]
cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8
cache_addw( ORR(dest_reg, templo1) ); // orr dest_reg, templo1
} else {
} else
#endif
{
cache_addw( LDRH_IMM(dest_reg, data_reg, 0) ); // ldrh dest_reg, [data_reg]
}
}
@ -236,8 +333,10 @@ static void gen_mov_word_to_reg_helper(HostReg dest_reg,void* data,bool dword,Ho
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
if (!gen_mov_memval_to_reg(dest_reg, data, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)data);
gen_mov_word_to_reg_helper(dest_reg, data, dword, templo2);
}
}
// move a 16bit constant value into dest_reg
@ -246,10 +345,58 @@ static void INLINE gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
}
// helper function
static bool gen_mov_memval_from_reg_helper(HostReg src_reg, Bit32u data, Bitu size, HostReg addr_reg, Bit32u addr_data) {
switch (size) {
case 4:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 3) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 128) && (((data - addr_data) & 3) == 0)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STR_IMM(src_reg, templo2, data - addr_data) ); // str src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 2:
#if !defined(C_UNALIGNED_MEMORY)
if ((data & 1) == 0)
#endif
{
if ((data >= addr_data) && (data < addr_data + 64) && (((data - addr_data) & 1) == 0)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRH_IMM(src_reg, templo2, data - addr_data) ); // strh src_reg, [templo2, #(data - addr_data)]
return true;
}
}
break;
case 1:
if ((data >= addr_data) && (data < addr_data + 32)) {
cache_addw( MOV_LO_HI(templo2, addr_reg) ); // mov templo2, addr_reg
cache_addw( STRB_IMM(src_reg, templo2, data - addr_data) ); // strb src_reg, [templo2, #(data - addr_data)]
return true;
}
default:
break;
}
return false;
}
// helper function
static bool gen_mov_memval_from_reg(HostReg src_reg, void *dest, Bitu size) {
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_REGS_ADDR, (Bit32u)&cpu_regs)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, readdata_addr, (Bit32u)&core_dynrec.readdata)) return true;
if (gen_mov_memval_from_reg_helper(src_reg, (Bit32u)dest, size, FC_SEGS_ADDR, (Bit32u)&Segs)) return true;
return false;
}
// helper function for gen_mov_word_from_reg
static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword, HostReg data_reg) {
// alignment....
if (dword) {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 3) {
if ( ((Bit32u)dest & 3) == 2 ) {
cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
@ -268,16 +415,21 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
cache_addw( LSR_IMM(templo1, templo1, 24) ); // lsr templo1, templo1, #24
cache_addw( STRB_IMM(templo1, data_reg, 3) ); // strb templo1, [data_reg, #3]
}
} else {
} else
#endif
{
cache_addw( STR_IMM(src_reg, data_reg, 0) ); // str src_reg, [data_reg]
}
} else {
#if !defined(C_UNALIGNED_MEMORY)
if ((Bit32u)dest & 1) {
cache_addw( STRB_IMM(src_reg, data_reg, 0) ); // strb src_reg, [data_reg]
cache_addw( MOV_REG(templo1, src_reg) ); // mov templo1, src_reg
cache_addw( LSR_IMM(templo1, templo1, 8) ); // lsr templo1, templo1, #8
cache_addw( STRB_IMM(templo1, data_reg, 1) ); // strb templo1, [data_reg, #1]
} else {
} else
#endif
{
cache_addw( STRH_IMM(src_reg, data_reg, 0) ); // strh src_reg, [data_reg]
}
}
@ -285,8 +437,10 @@ static void gen_mov_word_from_reg_helper(HostReg src_reg,void* dest,bool dword,
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
if (!gen_mov_memval_from_reg(src_reg, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_from_reg_helper(src_reg, dest, dword, templo2);
}
}
// move an 8bit value from memory into dest_reg
@ -294,8 +448,10 @@ static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
if (!gen_mov_memval_to_reg(dest_reg, data, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)data);
cache_addw( LDRB_IMM(dest_reg, templo1, 0) ); // ldrb dest_reg, [templo1]
}
}
// move an 8bit value from memory into dest_reg
@ -324,8 +480,10 @@ static void INLINE gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
if (!gen_mov_memval_from_reg(src_reg, dest, 1)) {
gen_mov_dword_to_reg_imm(templo1, (Bit32u)dest);
cache_addw( STRB_IMM(src_reg, templo1, 0) ); // strb src_reg, [templo1]
}
}
@ -362,16 +520,51 @@ static void gen_add(HostReg reg,void* op) {
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
Bit32u imm2, scale;
if(!imm) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_addw( ADD_IMM8(reg, imm) ); // add reg, #imm
} else if (imm2 <= 255) {
cache_addw( SUB_IMM8(reg, imm2) ); // sub reg, #(-imm)
} else {
if (val_single_shift(imm2, &scale)) {
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( SUB_REG(reg, reg, templo1) ); // sub reg, reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_addw( ADD_REG(reg, reg, templo1) ); // add reg, reg, templo1
}
}
}
// and a 32bit constant value with a full register
static void gen_and_imm(HostReg reg,Bit32u imm) {
if(imm == 0xffffffff) return;
gen_mov_dword_to_reg_imm(templo1, imm);
cache_addw( AND(reg, templo1) ); // and reg, templo1
Bit32u imm2, scale;
imm2 = ~imm;
if(!imm2) return;
if (!imm) {
cache_addw( MOV_IMM(reg, 0) ); // mov reg, #0
} else {
if (val_single_shift(imm2, &scale)) {
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( BIC(reg, templo1) ); // bic reg, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_addw( AND(reg, templo1) ); // and reg, templo1
}
}
}
@ -386,66 +579,65 @@ static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_direct_dword(dest,(Bit32u)imm);
}
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
if (imm >= 0) {
cache_addw( ADD_IMM8(templo3, (Bit32s)imm) ); // add templo3, #(imm)
} else {
cache_addw( SUB_IMM8(templo3, -((Bit32s)imm)) ); // sub templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
gen_add_imm(templo3, imm);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
if(!imm) return;
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, 1, templo2);
if (imm >= 0) {
cache_addw( SUB_IMM8(templo3, (Bit32s)imm) ); // sub templo3, #(imm)
} else {
cache_addw( ADD_IMM8(templo3, -((Bit32s)imm)) ); // add templo3, #(-imm)
}
gen_mov_word_from_reg_helper(templo3, dest, 1, templo2);
// add an 8bit constant value to a dword memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
gen_add_direct_word(dest, (Bit32s)imm, 1);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
Bit32u imm2, scale;
if (!dword) imm &= 0xffff;
if(!imm) return;
if (dword && ( (imm<128) || (imm>=0xffffff80) ) ) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
if (!gen_mov_memval_to_reg(templo3, dest, (dword)?4:2)) {
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
}
gen_mov_dword_to_reg_imm(templo2, (Bit32u)dest);
gen_mov_word_to_reg_helper(templo3, dest, dword, templo2);
if (dword) {
gen_mov_dword_to_reg_imm(templo1, imm);
imm2 = (Bit32u) (-((Bit32s)imm));
if (imm <= 255) {
cache_addw( SUB_IMM8(templo3, imm) ); // sub templo3, #imm
} else if (imm2 <= 255) {
cache_addw( ADD_IMM8(templo3, imm2) ); // add templo3, #(-imm)
} else {
gen_mov_word_to_reg_imm(templo1, (Bit16u)imm);
if (val_single_shift(imm2, &scale)) {
cache_addw( MOV_IMM(templo1, imm2 >> scale) ); // mov templo1, #(~imm >> scale)
if (scale) {
cache_addw( LSL_IMM(templo1, templo1, scale) ); // lsl templo1, templo1, #scale
}
cache_addw( ADD_REG(templo3, templo3, templo1) ); // add templo3, templo3, templo1
} else {
gen_mov_dword_to_reg_imm(templo1, imm);
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
}
}
cache_addw( SUB_REG(templo3, templo3, templo1) ); // sub templo3, templo3, templo1
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
if (!gen_mov_memval_from_reg(templo3, dest, (dword)?4:2)) {
gen_mov_word_from_reg_helper(templo3, dest, dword, templo2);
}
}
// subtract an 8bit constant value from a dword memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
gen_sub_direct_word(dest, (Bit32s)imm, 1);
}
// effective address calculation, destination is dest_reg
@ -491,7 +683,7 @@ static void INLINE gen_call_function_raw(void * func) {
// switch from arm to thumb state
cache_addd(0xe2800000 + (templo1 << 12) + (HOST_pc << 16) + (1)); // add templo1, pc, #1
cache_addd(0xe12fff10 + (templo1)); // bx templo1
// thumb state from now on
}
@ -537,18 +729,20 @@ static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
static void gen_jmp_ptr(void * ptr,Bits imm=0) {
gen_mov_word_to_reg(templo3, ptr, 1);
if (imm) {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_addw( ADD_REG(templo3, templo3, templo2) ); // add templo3, templo3, templo2
}
#if (1)
// (*ptr) should be word aligned
#if !defined(C_UNALIGNED_MEMORY)
// (*ptr) should be word aligned
if ((imm & 0x03) == 0) {
cache_addw( LDR_IMM(templo2, templo3, 0) ); // ldr templo2, [templo3]
} else
#endif
{
if ((imm >= 0) && (imm < 128) && ((imm & 3) == 0)) {
cache_addw( LDR_IMM(templo2, templo3, imm) ); // ldr templo2, [templo3, #imm]
} else {
gen_mov_dword_to_reg_imm(templo2, imm);
cache_addw( LDR_REG(templo2, templo3, templo2) ); // ldr templo2, [templo3, templo2]
}
#if !defined(C_UNALIGNED_MEMORY)
} else {
gen_add_imm(templo3, imm);
cache_addw( LDRB_IMM(templo2, templo3, 0) ); // ldrb templo2, [templo3]
cache_addw( LDRB_IMM(templo1, templo3, 1) ); // ldrb templo1, [templo3, #1]
cache_addw( LSL_IMM(templo1, templo1, 8) ); // lsl templo1, templo1, #8
@ -560,6 +754,7 @@ static void gen_jmp_ptr(void * ptr,Bits imm=0) {
cache_addw( LSL_IMM(templo1, templo1, 24) ); // lsl templo1, templo1, #24
cache_addw( ORR(templo2, templo1) ); // orr templo2, templo1
}
#endif
// increase jmp address to keep thumb state
cache_addw( ADD_IMM3(templo2, templo2, 1) ); // add templo2, templo2, #1
@ -650,50 +845,53 @@ static void INLINE gen_fill_branch_long(Bit32u data) {
}
static void gen_run_code(void) {
// switch from arm to thumb state
cache_addd(0xe2800000 + (HOST_r3 << 12) + (HOST_pc << 16) + (1)); // add r3, pc, #1
cache_addd(0xe12fff10 + (HOST_r3)); // bx r3
Bit8u *pos1, *pos2, *pos3;
// thumb state from now on
cache_addw(0xb500); // push {lr}
cache_addw( MOV_LO_HI(HOST_r3, FC_SEGS_ADDR) ); // mov r3, FC_SEGS_ADDR
cache_addw( MOV_LO_HI(HOST_r2, FC_REGS_ADDR) ); // mov r2, FC_REGS_ADDR
cache_addw(0xb4fc); // push {r2,r3,v1-v4}
#if (__ARM_EABI__)
// 8-byte stack alignment
cache_addd(0xe92d4ff0); // stmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe92d4df0); // stmfd sp!, {v1-v5,v7,v8,lr}
#endif
// adr: 16
cache_addw( LDR_PC_IMM(HOST_r3, 64 - (16 + 4)) ); // ldr r3, [pc, #(&Segs)]
// adr: 18
cache_addw( LDR_PC_IMM(HOST_r2, 68 - (18 + 2)) ); // ldr r2, [pc, #(&cpu_regs)]
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_r0, HOST_r0, 1, 0) ); // add r0, r0, #1
// align 4
cache_addw( ADD_LO_PC_IMM(HOST_r3, 8) ); // add r3, pc, #8
cache_addw( ADD_IMM8(HOST_r0, 1) ); // add r0, #1
cache_addw( ADD_IMM8(HOST_r3, 1) ); // add r3, #1
cache_addw(0xb408); // push {r3}
cache_addw( BX(HOST_r0) ); // bx r0
cache_addw( NOP ); // nop
pos1 = cache.pos;
cache_addd( 0 );
pos2 = cache.pos;
cache_addd( 0 );
pos3 = cache.pos;
cache_addd( 0 );
// align 4
cache_addw(0xbcfc); // pop {r2,r3,v1-v4}
cache_addw( MOV_HI_LO(FC_SEGS_ADDR, HOST_r3) ); // mov FC_SEGS_ADDR, r3
cache_addw( MOV_HI_LO(FC_REGS_ADDR, HOST_r2) ); // mov FC_REGS_ADDR, r2
cache_addd( ARM_ADD_IMM(HOST_lr, HOST_pc, 4, 0) ); // add lr, pc, #4
cache_addd( ARM_STR_IMM_M_W(HOST_lr, HOST_sp, 4) ); // str lr, [sp, #-4]!
cache_addd( ARM_BX(HOST_r0) ); // bx r0
cache_addw(0xbc08); // pop {r3}
cache_addw( BX(HOST_r3) ); // bx r3
#if (__ARM_EABI__)
cache_addd(0xe8bd4ff0); // ldmfd sp!, {v1-v8,lr}
#else
cache_addd(0xe8bd4df0); // ldmfd sp!, {v1-v5,v7,v8,lr}
#endif
cache_addd( ARM_BX(HOST_lr) ); // bx lr
// fill up to 64 bytes
cache_addw( NOP ); // nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
cache_addd( NOP | (NOP << 16) ); // nop, nop
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
// adr: 64
*(Bit32u*)pos1 = ARM_LDR_IMM(FC_SEGS_ADDR, HOST_pc, cache.pos - (pos1 + 8)); // ldr FC_SEGS_ADDR, [pc, #(&Segs)]
cache_addd((Bit32u)&Segs); // address of "Segs"
// adr: 68
*(Bit32u*)pos2 = ARM_LDR_IMM(FC_REGS_ADDR, HOST_pc, cache.pos - (pos2 + 8)); // ldr FC_REGS_ADDR, [pc, #(&cpu_regs)]
cache_addd((Bit32u)&cpu_regs); // address of "cpu_regs"
*(Bit32u*)pos3 = ARM_LDR_IMM(readdata_addr, HOST_pc, cache.pos - (pos3 + 8)); // ldr readdata_addr, [pc, #(&core_dynrec.readdata)]
cache_addd((Bit32u)&core_dynrec.readdata); // address of "core_dynrec.readdata"
// align cache.pos to 32 bytes
if ((((Bitu)cache.pos) & 0x1f) != 0) {
cache.pos = cache.pos + (32 - (((Bitu)cache.pos) & 0x1f));
}
}
// return from a function
@ -1023,7 +1221,11 @@ static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
}
#endif
static void cache_block_before_close(void) { }
static void cache_block_before_close(void) {
if ((((Bit32u)cache.pos) & 3) != 0) {
cache_addw( NOP ); // nop
}
}
#ifdef DRC_USE_SEGS_ADDR

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,20 +11,26 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* ARMv4 (little endian) backend (switcher) by M-HT */
/* ARMv4/ARMv7 (little endian) backend (switcher) by M-HT */
#include "risc_armv4le-common.h"
// choose your destiny:
#include "risc_armv4le-thumb-niw.h"
//#include "risc_armv4le-thumb-iw.h"
//#include "risc_armv4le-thumb.h"
//#include "risc_armv4le-s3.h"
//#include "risc_armv4le-o3.h"
#if C_TARGETCPU == ARMV7LE
#include "risc_armv4le-o3.h"
#else
#if defined(__THUMB_INTERWORK__)
#include "risc_armv4le-thumb-iw.h"
#else
#include "risc_armv4le-o3.h"
// #include "risc_armv4le-thumb-niw.h"
// #include "risc_armv4le-thumb.h"
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ -56,11 +56,16 @@ typedef Bit8u HostReg;
// then define DRC_PROTECT_ADDR_REG above
#define FC_ADDR HOST_EBX
#if defined (_WIN64)
#define FC_OP1 HOST_ECX
#define FC_OP2 HOST_EDX
#else
// register that holds the first parameter
#define FC_OP1 HOST_EDI
// register that holds the second parameter
#define FC_OP2 HOST_ESI
#endif
// special register that holds the third parameter for _R3 calls (byte accessible)
#define FC_OP3 HOST_EAX
@ -78,55 +83,105 @@ typedef Bit8u HostReg;
// move a full register from reg_src to reg_dst
static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) {
if (reg_dst==reg_src) return;
cache_addb(0x8b); // mov reg_dst,reg_src
cache_addb(0xc0+(reg_dst<<3)+reg_src);
}
static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm);
static INLINE void gen_reg_memaddr(HostReg reg,void* data) {
Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5);
if ((diff<0x80000000LL) && (diff>-0x80000000LL)) {
// This function generates an instruction with register addressing and a memory location
static INLINE void gen_reg_memaddr(HostReg reg,void* data,Bit8u op,Bit8u prefix=0) {
Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+(prefix?7:6));
// if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { //clang messes itself up on this...
if ( (diff>>63) == (diff>>31) ) { //signed bit extend, test to see if value fits in a Bit32s
// mov reg,[rip+diff] (or similar, depending on the op) to fetch *data
if(prefix) cache_addb(prefix);
cache_addb(op);
cache_addb(0x05+(reg<<3));
// RIP-relative addressing is offset after the instruction
cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL));
} else if ((Bit64u)data<0x100000000LL) {
// mov reg,[data] (or similar, depending on the op) when absolute address of data is <4GB
if(prefix) cache_addb(prefix);
cache_addb(op);
cache_addw(0x2504+(reg<<3));
cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL));
} else {
E_Exit("DRC64:Unhandled memory reference");
// load 64-bit data into tmp_reg and do mov reg,[tmp_reg] (or similar, depending on the op)
HostReg tmp_reg = HOST_EAX;
if(reg == HOST_EAX) tmp_reg = HOST_ECX;
cache_addb(0x50+tmp_reg); // push rax/rcx
gen_mov_reg_qword(tmp_reg,(Bit64u)data);
if(prefix) cache_addb(prefix);
cache_addb(op);
cache_addb(tmp_reg+(reg<<3));
cache_addb(0x58+tmp_reg); // pop rax/rcx
}
}
static INLINE void gen_memaddr(Bitu op,void* data,Bitu off) {
Bit64s diff;
diff = (Bit64s)data-((Bit64s)cache.pos+off+5);
if ((diff<0x80000000LL) && (diff>-0x80000000LL)) {
// Same as above, but with immediate addressing and a memory location
static INLINE void gen_memaddr(Bitu modreg,void* data,Bitu off,Bitu imm,Bit8u op,Bit8u prefix=0) {
Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+off+(prefix?7:6));
// if ((diff<0x80000000LL) && (diff>-0x80000000LL)) {
if ( (diff>>63) == (diff>>31) ) {
// RIP-relative addressing is offset after the instruction
cache_addb(op+1);
cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL));
if(prefix) cache_addb(prefix);
cache_addw(op+((modreg+1)<<8));
cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL));
switch(off) {
case 1: cache_addb(((Bit8u)imm&0xff)); break;
case 2: cache_addw(((Bit16u)imm&0xffff)); break;
case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
}
} else if ((Bit64u)data<0x100000000LL) {
cache_addb(op);
if(prefix) cache_addb(prefix);
cache_addw(op+(modreg<<8));
cache_addb(0x25);
cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL));
switch(off) {
case 1: cache_addb(((Bit8u)imm&0xff)); break;
case 2: cache_addw(((Bit16u)imm&0xffff)); break;
case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
}
} else {
E_Exit("DRC64:Unhandled memory reference");
HostReg tmp_reg = HOST_EAX;
cache_addb(0x50+tmp_reg); // push rax
gen_mov_reg_qword(tmp_reg,(Bit64u)data);
if(prefix) cache_addb(prefix);
cache_addw(op+((modreg-4+tmp_reg)<<8));
switch(off) {
case 1: cache_addb(((Bit8u)imm&0xff)); break;
case 2: cache_addw(((Bit16u)imm&0xffff)); break;
case 4: cache_addd(((Bit32u)imm&0xffffffff)); break;
}
cache_addb(0x58+tmp_reg); // pop rax
}
}
// move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg
// 16bit moves may destroy the upper 16bit of the destination register
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x8b); // mov reg,[data]
gen_reg_memaddr(dest_reg,data);
static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword,Bit8u prefix=0) {
if (!dword) gen_reg_memaddr(dest_reg,data,0xb7,0x0f); // movzx reg,[data] - zero extend data, fixes LLVM compile where the called function does not extend the parameters
else gen_reg_memaddr(dest_reg,data,0x8b,prefix); // mov reg,[data]
}
// move a 16bit constant value into dest_reg
// the upper 16bit of the destination register may be destroyed
static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
cache_addd((Bit32u)imm);
}
// move a 32bit constant value into dest_reg
@ -135,11 +190,20 @@ static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) {
cache_addd(imm);
}
// move a 64bit constant value into a full register
static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) {
if (imm==(Bit32u)imm) {
gen_mov_dword_to_reg_imm(dest_reg, (Bit32u)imm);
return;
}
cache_addb(0x48);
cache_addb(0xb8+dest_reg); // mov dest_reg,imm
cache_addq(imm);
}
// move 32bit (dword==true) or 16bit (dword==false) of a register into memory
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
if (!dword) cache_addb(0x66);
cache_addb(0x89); // mov [data],reg
gen_reg_memaddr(src_reg,dest);
static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword,Bit8u prefix=0) {
gen_reg_memaddr(src_reg,dest,0x89,(dword?prefix:0x66)); // mov [data],reg
}
// move an 8bit value from memory into dest_reg
@ -147,8 +211,7 @@ static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) {
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
cache_addb(0x8a); // mov reg,[data]
gen_reg_memaddr(dest_reg,data);
gen_reg_memaddr(dest_reg,data,0xb6,0x0f); // movzx reg,[data]
}
// move an 8bit value from memory into dest_reg
@ -156,9 +219,7 @@ static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) {
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
cache_addb(0x66);
cache_addb(0x8b); // mov reg,[data]
gen_reg_memaddr(dest_reg,data);
gen_reg_memaddr(dest_reg,data,0xb6,0x0f); // movzx reg,[data]
}
// move an 8bit constant value into dest_reg
@ -166,8 +227,8 @@ static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) {
// this function does not use FC_OP1/FC_OP2 as dest_reg as these
// registers might not be directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
cache_addb(0xb0+dest_reg); // mov reg,imm
cache_addb(imm);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addd((Bit32u)imm);
}
// move an 8bit constant value into dest_reg
@ -175,15 +236,13 @@ static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) {
// this function can use FC_OP1/FC_OP2 as dest_reg which are
// not directly byte-accessible on some architectures
static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) {
cache_addb(0x66);
cache_addb(0xb8+dest_reg); // mov reg,imm
cache_addw(imm);
cache_addd((Bit32u)imm);
}
// move the lowest 8bit of a register into memory
static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) {
cache_addb(0x88); // mov [data],reg
gen_reg_memaddr(src_reg,dest);
gen_reg_memaddr(src_reg,dest,0x88); // mov byte [data],reg
}
@ -206,12 +265,12 @@ static void gen_extend_word(bool sign,HostReg reg) {
// add a 32bit value from memory to a full register
static void gen_add(HostReg reg,void* op) {
cache_addb(0x03); // add reg,[data]
gen_reg_memaddr(reg,op);
gen_reg_memaddr(reg,op,0x03); // add reg,[data]
}
// add a 32bit constant value to a full register
static void gen_add_imm(HostReg reg,Bit32u imm) {
if (!imm) return;
cache_addw(0xc081+(reg<<8)); // add reg,imm
cache_addd(imm);
}
@ -226,72 +285,47 @@ static void gen_and_imm(HostReg reg,Bit32u imm) {
// move a 32bit constant value into memory
static void gen_mov_direct_dword(void* dest,Bit32u imm) {
cache_addb(0xc7); // mov [data],imm
gen_memaddr(0x04,dest,4);
cache_addd(imm);
gen_memaddr(0x4,dest,4,imm,0xc7); // mov [data],imm
}
// move a 64bit constant value into a full register
static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) {
cache_addb(0x48);
cache_addb(0xb8+dest_reg); // mov dest_reg,imm
cache_addq(imm);
}
// move an address into memory
static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) {
gen_mov_reg_qword(HOST_EAX,imm);
cache_addb(0x48);
gen_mov_word_from_reg(HOST_EAX,dest,true);
gen_mov_word_from_reg(HOST_EAX,dest,true,0x48); // 0x48 prefixes full 64-bit mov
}
// add an 8bit constant value to a memory value
static void gen_add_direct_byte(void* dest,Bit8s imm) {
cache_addb(0x83); // add [data],imm
gen_memaddr(0x4,dest,1);
cache_addb(imm);
if (!imm) return;
gen_memaddr(0x4,dest,1,imm,0x83); // add [data],imm
}
// add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value
static void gen_add_direct_word(void* dest,Bit32u imm,bool dword) {
if (!imm) return;
if ((imm<128) && dword) {
gen_add_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addb(0x81); // add [data],imm
if (dword) {
gen_memaddr(0x4,dest,4); // size of following immediate value
cache_addd((Bit32u)imm);
} else {
gen_memaddr(0x4,dest,2); // size of following immediate value
cache_addw((Bit16u)imm);
}
gen_memaddr(0x4,dest,(dword?4:2),imm,0x81,(dword?0:0x66)); // add [data],imm
}
// subtract an 8bit constant value from a memory value
static void gen_sub_direct_byte(void* dest,Bit8s imm) {
cache_addb(0x83); // sub [data],imm
gen_memaddr(0x2c,dest,1);
cache_addb(imm);
if (!imm) return;
gen_memaddr(0x2c,dest,1,imm,0x83);
}
// subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value
static void gen_sub_direct_word(void* dest,Bit32u imm,bool dword) {
if (!imm) return;
if ((imm<128) && dword) {
gen_sub_direct_byte(dest,(Bit8s)imm);
return;
}
if (!dword) cache_addb(0x66);
cache_addw(0x81); // sub [data],imm
if (dword) {
gen_memaddr(0x2c,dest,4); // size of following immediate value
cache_addd((Bit32u)imm);
} else {
gen_memaddr(0x2c,dest,2); // size of following immediate value
cache_addw((Bit16u)imm);
}
gen_memaddr(0x2c,dest,(dword?4:2),imm,0x81,(dword?0:0x66)); // sub [data],imm
}
@ -341,58 +375,17 @@ static INLINE void gen_lea(HostReg dest_reg,Bitu scale,Bits imm) {
// generate a call to a parameterless function
static void INLINE gen_call_function_raw(void * func) {
cache_addb(0x48);
cache_addw(0xec83);
cache_addb(0x08); // sub rsp,0x08 (align stack to 16 byte boundary)
cache_addb(0x48);
cache_addb(0xb8); // mov reg,imm64
cache_addw(0xb848);
cache_addq((Bit64u)func);
cache_addw(0xd0ff);
cache_addb(0x48);
cache_addw(0xc483);
cache_addb(0x08); // add rsp,0x08 (reset alignment)
}
// generate a call to a function with paramcount parameters
// note: the parameters are loaded in the architecture specific way
// using the gen_load_param_ functions below
static Bit64u INLINE gen_call_function_setup(void * func,Bitu paramcount,bool fastcall=false) {
// align the stack
cache_addb(0x48);
cache_addw(0xc48b); // mov rax,rsp
cache_addb(0x48);
cache_addw(0xec83); // sub rsp,0x08
cache_addb(0x08); // 0x08==return address pushed onto stack by call
cache_addb(0x48);
cache_addw(0xe483); // and esp,0xfffffffffffffff0
cache_addb(0xf0);
cache_addb(0x48);
cache_addw(0xc483); // add rsp,0x08
cache_addb(0x08);
// stack is 16 byte aligned now
cache_addb(0x50); // push rax (==old rsp)
// returned address relates to where the address is stored in gen_call_function_raw
Bit64u proc_addr=(Bit64u)cache.pos-4;
// Do the actual call to the procedure
cache_addb(0x48);
cache_addb(0xb8); // mov reg,imm64
cache_addq((Bit64u)func);
cache_addw(0xd0ff);
// restore stack
cache_addb(0x5c); // pop rsp
Bit64u proc_addr = (Bit64u)cache.pos;
gen_call_function_raw(func);
return proc_addr;
}
@ -407,14 +400,14 @@ static void INLINE gen_load_param_imm(Bitu imm,Bitu param) {
case 1: // mov param2,imm32
gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm);
break;
#if defined (_MSC_VER)
case 2: // mov r8,imm32
cache_addw(0xb849);
cache_addq((Bit32u)imm);
#if defined (_WIN64)
case 2: // mov r8d,imm32
cache_addw(0xb841);
cache_addd((Bit32u)imm);
break;
case 3: // mov r9,imm32
cache_addw(0xb949);
cache_addq((Bit32u)imm);
case 3: // mov r9d,imm32
cache_addw(0xb941);
cache_addd((Bit32u)imm);
break;
#else
case 2: // mov rdx,imm32
@ -440,7 +433,7 @@ static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) {
case 1: // mov param2,addr64
gen_mov_reg_qword(FC_OP2,addr);
break;
#if defined (_MSC_VER)
#if defined (_WIN64)
case 2: // mov r8,addr64
cache_addw(0xb849);
cache_addq(addr);
@ -473,14 +466,14 @@ static void INLINE gen_load_param_reg(Bitu reg,Bitu param) {
case 1: // mov param2,reg&7
gen_mov_regs(FC_OP2,reg&7);
break;
#if defined (_MSC_VER)
#if defined (_WIN64)
case 2: // mov r8,reg&7
cache_addb(0x49);
gen_mov_regs(0,reg&7);
cache_addw(0x8949);
cache_addb(0xc0 + ((reg & 7) << 3));
break;
case 3: // mov r9,reg&7
cache_addb(0x49);
gen_mov_regs(1,reg&7);
cache_addw(0x8949);
cache_addb(0xc1 + ((reg & 7) << 3));
break;
#else
case 2: // mov rdx,reg&7
@ -506,20 +499,18 @@ static void INLINE gen_load_param_mem(Bitu mem,Bitu param) {
case 1: // mov param2,[mem]
gen_mov_word_to_reg(FC_OP2,(void*)mem,true);
break;
#if defined (_MSC_VER)
case 2: // mov r8,[mem]
cache_addb(0x49);
gen_mov_word_to_reg(0,(void*)mem,true);
#if defined (_WIN64)
case 2: // mov r8d,[mem]
gen_mov_word_to_reg(0,(void*)mem,true,0x44); // 0x44, use x64 rXd regs
break;
case 3: // mov r9,[mem]
cache_addb(0x49);
gen_mov_word_to_reg(1,(void*)mem,true);
case 3: // mov r9d,[mem]
gen_mov_word_to_reg(1,(void*)mem,true,0x44); // 0x44, use x64 rXd regs
break;
#else
case 2: // mov rdx,[mem]
case 2: // mov edx,[mem]
gen_mov_word_to_reg(HOST_EDX,(void*)mem,true);
break;
case 3: // mov rcx,[mem]
case 3: // mov ecx,[mem]
gen_mov_word_to_reg(HOST_ECX,(void*)mem,true);
break;
#endif
@ -610,16 +601,19 @@ static void gen_fill_branch_long(Bit64u data) {
*(Bit32u*)data=(Bit32u)((Bit64u)cache.pos-data-4);
}
static void gen_run_code(void) {
cache_addb(0x53); // push rbx
cache_addw(0xd0ff+(FC_OP1<<8)); // call rdi
cache_addb(0x5b); // pop rbx
cache_addw(0x5355); // push rbp,rbx
cache_addb(0x56); // push rsi
cache_addd(0x20EC8348); // sub rsp, 32
cache_addb(0x48);cache_addw(0x2D8D);cache_addd(2); // lea rbp, [rip+2]
cache_addw(0xE0FF+(FC_OP1<<8)); // jmp FC_OP1
cache_addd(0x20C48348); // add rsp, 32
cache_addd(0xC35D5B5E); // pop rsi,rbx,rbp;ret
}
// return from a function
static void gen_return_function(void) {
cache_addb(0xc3); // ret
cache_addw(0xE5FF); // jmp rbp
}
#ifdef DRC_FLAGS_INVALIDATION
@ -634,94 +628,77 @@ static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) {
case t_ADDb:
case t_ADDw:
case t_ADDd:
*(Bit32u*)(pos+0)=0xf001f889; // mov eax,edi; add eax,esi
*(Bit32u*)(pos+4)=0x90900eeb; // skip
// mov eax,FC_OP1; add eax,FC_OP2
*(Bit32u*)(pos+0)=0xc001c089+(FC_OP1<<11)+(FC_OP2<<27);
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_ORb:
case t_ORw:
case t_ORd:
*(Bit32u*)(pos+0)=0xf009f889; // mov eax,edi; or eax,esi
*(Bit32u*)(pos+4)=0x90900eeb; // skip
// mov eax,FC_OP1; or eax,FC_OP2
*(Bit32u*)(pos+0)=0xc009c089+(FC_OP1<<11)+(FC_OP2<<27);
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_ANDb:
case t_ANDw:
case t_ANDd:
*(Bit32u*)(pos+0)=0xf021f889; // mov eax,edi; and eax,esi
*(Bit32u*)(pos+4)=0x90900eeb; // skip
// mov eax,FC_OP1; and eax,FC_OP2
*(Bit32u*)(pos+0)=0xc021c089+(FC_OP1<<11)+(FC_OP2<<27);
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_SUBb:
case t_SUBw:
case t_SUBd:
*(Bit32u*)(pos+0)=0xf029f889; // mov eax,edi; sub eax,esi
*(Bit32u*)(pos+4)=0x90900eeb; // skip
// mov eax,FC_OP1; sub eax,FC_OP2
*(Bit32u*)(pos+0)=0xc029c089+(FC_OP1<<11)+(FC_OP2<<27);
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_XORb:
case t_XORw:
case t_XORd:
*(Bit32u*)(pos+0)=0xf031f889; // mov eax,edi; xor eax,esi
*(Bit32u*)(pos+4)=0x90900eeb; // skip
// mov eax,FC_OP1; xor eax,FC_OP2
*(Bit32u*)(pos+0)=0xc031c089+(FC_OP1<<11)+(FC_OP2<<27);
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_CMPb:
case t_CMPw:
case t_CMPd:
case t_TESTb:
case t_TESTw:
case t_TESTd:
*(Bit32u*)(pos+0)=0x909012eb; // skip
*(Bit32u*)(pos+0)=0x90900aeb; // skip
*(Bit32u*)(pos+4)=0x90909090;
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_INCb:
case t_INCw:
case t_INCd:
*(Bit32u*)(pos+0)=0xc0fff889; // mov eax,edi; inc eax
*(Bit32u*)(pos+4)=0x90900eeb; // skip
*(Bit32u*)(pos+0)=0xc0ffc089+(FC_OP1<<11); // mov eax,ecx; inc eax
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_DECb:
case t_DECw:
case t_DECd:
*(Bit32u*)(pos+0)=0xc8fff889; // mov eax,edi; dec eax
*(Bit32u*)(pos+4)=0x90900eeb; // skip
*(Bit32u*)(pos+0)=0xc8ffc089+(FC_OP1<<11); // mov eax, FC_OP1; dec eax
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
return;
case t_NEGb:
case t_NEGw:
case t_NEGd:
*(Bit32u*)(pos+0)=0xd8f7f889; // mov eax,edi; neg eax
*(Bit32u*)(pos+4)=0x90900eeb; // skip
*(Bit32u*)(pos+0)=0xd8f7c089+(FC_OP1<<11); // mov eax, FC_OP1; neg eax
*(Bit32u*)(pos+4)=0x909006eb; // skip
*(Bit32u*)(pos+8)=0x90909090;
*(Bit32u*)(pos+12)=0x90909090;
*(Bit32u*)(pos+16)=0x90909090;
break;
default:
*(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer
break;
return;
}
#else
*(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer
#endif
*(Bit64u*)(pos+2)=(Bit64u)fct_ptr; // fill function pointer
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "dosbox.h"

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
switch (inst.code.load) {
@ -186,15 +186,19 @@ l_M_Ed:
case M_GRP:
inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch;
case M_GRP_Ib:
inst_op2_d=Fetchb();
case M_SHIFT_Ib:
inst_op2_d=Fetchb() & 0x1f;
if (!inst_op2_d)
break;
inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch;
case M_GRP_CL:
inst_op2_d=reg_cl;
case M_SHIFT_CL:
inst_op2_d=reg_cl & 0x1f;
if (!inst_op2_d)
break;
inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch;
case M_GRP_1:
case M_SHIFT_1:
inst_op2_d=1;
inst.code=Groups[inst.code.op][inst.rm_index];
goto l_MODRMswitch;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#define SaveIP() reg_eip=(Bit32u)(inst.cseip-SegBase(cs));

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Do the actual opcode */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Big ass opcode table normal,double, 66 normal, 66 double */
@ -155,7 +155,7 @@ static OpCode OpCodeTable[1024]={
{L_Iw ,0 ,S_REGw ,REGI_SI},{L_Iw ,0 ,S_REGw ,REGI_DI},
/* 0xc0 - 0xc7 */
{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,6 ,0 ,M_GRP_Ib },
{L_MODRM ,5 ,0 ,M_SHIFT_Ib },{L_MODRM ,6 ,0 ,M_SHIFT_Ib },
{L_POPw ,0 ,S_IPIw ,0 },{L_POPw ,0 ,S_IP ,0 },
{L_MODRM ,O_SEGES ,S_SEGGw,M_Efw },{L_MODRM ,O_SEGDS ,S_SEGGw,M_Efw },
{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ew ,M_Iw },
@ -166,8 +166,8 @@ static OpCode OpCodeTable[1024]={
{L_INTO ,O_INT ,0 ,0 },{D_IRETw ,0 ,0 ,0 },
/* 0xd0 - 0xd7 */
{L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,6 ,0 ,M_GRP_1 },
{L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,6 ,0 ,M_GRP_CL },
{L_MODRM ,5 ,0 ,M_SHIFT_1 },{L_MODRM ,6 ,0 ,M_SHIFT_1 },
{L_MODRM ,5 ,0 ,M_SHIFT_CL },{L_MODRM ,6 ,0 ,M_SHIFT_CL },
{L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 },
{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 },
//TODO FPU
@ -511,7 +511,7 @@ static OpCode OpCodeTable[1024]={
{L_Id ,0 ,S_REGd ,REGI_SI},{L_Id ,0 ,S_REGd ,REGI_DI},
/* 0x2c0 - 0x2c7 */
{L_MODRM ,5 ,0 ,M_GRP_Ib },{L_MODRM ,7 ,0 ,M_GRP_Ib },
{L_MODRM ,5 ,0 ,M_SHIFT_Ib },{L_MODRM ,7 ,0 ,M_SHIFT_Ib },
{L_POPd ,0 ,S_IPIw ,0 },{L_POPd ,0 ,S_IP ,0 },
{L_MODRM ,O_SEGES ,S_SEGGd,M_Efd },{L_MODRM ,O_SEGDS ,S_SEGGd,M_Efd },
{L_MODRM ,0 ,S_Eb ,M_Ib },{L_MODRM ,0 ,S_Ed ,M_Id },
@ -522,8 +522,8 @@ static OpCode OpCodeTable[1024]={
{L_INTO ,O_INT ,0 ,0 },{D_IRETd ,0 ,0 ,0 },
/* 0x2d0 - 0x2d7 */
{L_MODRM ,5 ,0 ,M_GRP_1 },{L_MODRM ,7 ,0 ,M_GRP_1 },
{L_MODRM ,5 ,0 ,M_GRP_CL },{L_MODRM ,7 ,0 ,M_GRP_CL },
{L_MODRM ,5 ,0 ,M_SHIFT_1 },{L_MODRM ,7 ,0 ,M_SHIFT_1 },
{L_MODRM ,5 ,0 ,M_SHIFT_CL },{L_MODRM ,7 ,0 ,M_SHIFT_CL },
{L_Ib ,O_AAM ,0 ,0 },{L_Ib ,O_AAD ,0 ,0 },
{D_SETALC ,0 ,0 ,0 },{D_XLAT ,0 ,0 ,0 },
/* 0x2d8 - 0x2df */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Write the data from the opcode */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
{
@ -88,6 +88,13 @@
di_index=(di_index+add_index) & add_mask;
}
break;
case R_INSD:
add_index<<=2;
for (;count>0;count--) {
SaveMd(di_base+di_index,IO_ReadD(reg_dx));
di_index=(di_index+add_index) & add_mask;
}
break;
case R_STOSB:
for (;count>0;count--) {
SaveMb(di_base+di_index,reg_al);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
enum {
@ -167,7 +167,8 @@ enum {
M_SEG,M_EA,
M_GRP,
M_GRP_Ib,M_GRP_CL,M_GRP_1,
//Special shift groups
M_SHIFT_1, M_SHIFT_Ib,M_SHIFT_CL,
M_POPw,M_POPd
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
@ -58,6 +58,8 @@ extern Bitu cycle_count;
#define CPU_PIC_CHECK 1
#define CPU_TRAP_CHECK 1
#define CPU_TRAP_DECODER CPU_Core_Normal_Trap_Run
#define OPCODE_NONE 0x000
#define OPCODE_0F 0x100
#define OPCODE_SIZE 0x200

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CASE_0F_W(0x00) /* GRP 6 Exxx */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CASE_D(0x01) /* ADD Ed,Gd */
@ -390,7 +390,7 @@
CPU_CALL(true,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -403,7 +403,7 @@
if (CPU_POPF(true)) RUNEXCEPTION();
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
goto decode_end;
}
#endif
@ -515,7 +515,7 @@
CPU_IRET(true,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -589,7 +589,7 @@
CPU_JMP(true,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -677,7 +677,7 @@
CPU_CALL(true,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -697,7 +697,7 @@
CPU_JMP(true,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CASE_0F_D(0x00) /* GRP 6 Exxx */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CASE_B(0x00) /* ADD Eb,Gb */
@ -564,7 +564,7 @@
CPU_CALL(false,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -579,7 +579,7 @@
if (CPU_POPF(false)) RUNEXCEPTION();
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
goto decode_end;
}
#endif
@ -780,7 +780,7 @@
CPU_IRET(false,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -919,7 +919,7 @@
CPU_JMP(false,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -1132,7 +1132,7 @@
CPU_CALL(false,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif
@ -1153,7 +1153,7 @@
CPU_JMP(false,newcs,newip,GETIP);
#if CPU_TRAP_CHECK
if (GETFLAG(TF)) {
cpudecoder=CPU_Core_Normal_Trap_Run;
cpudecoder=CPU_TRAP_DECODER;
return CBRET_NONE;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
enum STRING_OP {
@ -93,6 +93,13 @@ static void DoString(STRING_OP type) {
di_index=(di_index+add_index) & add_mask;
}
break;
case R_INSD:
add_index<<=2;
for (;count>0;count--) {
SaveMd(di_base+di_index,IO_ReadD(reg_dx));
di_index=(di_index+add_index) & add_mask;
}
break;
case R_STOSB:
for (;count>0;count--) {
SaveMb(di_base+di_index,reg_al);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2011 The DOSBox Team
* Copyright (C) 2002-2019 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -11,9 +11,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

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