mirror of
https://github.com/retro100/dosbox-wii.git
synced 2025-02-02 20:12:34 +01:00
Sync to DOSBox SVN r4301
This commit is contained in:
parent
03ba330e85
commit
b4f2a13f7f
11
COPYING
11
COPYING
@ -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.
|
||||
|
||||
|
86
ChangeLog
86
ChangeLog
@ -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
93
INSTALL
@ -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
|
||||
|
3
Makefile
3
Makefile
@ -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
26
NEWS
@ -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
48
README
@ -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).
|
||||
|
||||
|
||||
|
32
acinclude.m4
32
acinclude.m4
@ -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
0
autogen.sh
Normal file → Executable 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
67
include/midi.h
Normal 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
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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){}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
1278
src/cpu/core_dyn_x86/risc_x64.h
Normal file
1278
src/cpu/core_dyn_x86/risc_x64.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,®_eip,decode.big_op);
|
||||
gen_mov_word_to_reg(reg,®_eip,true); //get_extend_word will mask off the upper bits
|
||||
//gen_mov_word_to_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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
1238
src/cpu/core_dynrec/risc_armv8le.h
Normal file
1238
src/cpu/core_dynrec/risc_armv8le.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user