From 5d0f3a05e817872eaa1e3a359e381914309da9ac Mon Sep 17 00:00:00 2001 From: "Carl.Kenner" Date: Sat, 2 May 2009 22:37:32 +0000 Subject: [PATCH] DOSBox 0.71 --- AUTHORS | 13 +- ChangeLog | 56 +- INSTALL | 31 +- Makefile.in | 4 +- NEWS | 56 +- README | 217 +- THANKS | 9 +- config.guess | 21 +- config.h.in | 24 +- config.sub | 46 +- configure | 493 ++++- configure.in | 120 +- docs/Makefile.am | 2 +- docs/Makefile.in | 2 +- docs/PORTING | 48 + docs/dosbox.1 | 30 +- include/callback.h | 10 +- include/cpu.h | 16 +- include/dos_inc.h | 72 +- include/dos_system.h | 4 +- include/fpu.h | 4 +- include/inout.h | 4 +- include/mem.h | 2 +- include/paging.h | 8 +- include/pic.h | 2 +- include/regs.h | 2 +- include/render.h | 7 + include/setup.h | 6 +- include/shell.h | 4 +- src/Makefile.am | 12 +- src/Makefile.in | 8 +- src/cpu/Makefile.am | 4 +- src/cpu/Makefile.in | 10 +- src/cpu/callback.cpp | 24 +- src/cpu/core_dyn_x86.cpp | 10 +- src/cpu/core_dyn_x86/cache.h | 13 +- src/cpu/core_dyn_x86/decoder.h | 30 +- src/cpu/core_dyn_x86/dyn_fpu.h | 4 +- src/cpu/core_dyn_x86/dyn_fpu_dh.h | 6 +- src/cpu/core_dyn_x86/risc_x86.h | 14 +- src/cpu/core_dynrec.cpp | 323 +++ src/cpu/core_dynrec/Makefile.am | 2 + src/cpu/core_dynrec/Makefile.in | 332 +++ src/cpu/core_dynrec/cache.h | 642 ++++++ src/cpu/core_dynrec/decoder.h | 582 +++++ src/cpu/core_dynrec/decoder_basic.h | 1103 ++++++++++ src/cpu/core_dynrec/decoder_opcodes.h | 1416 +++++++++++++ src/cpu/core_dynrec/dyn_fpu.h | 681 ++++++ src/cpu/core_dynrec/operators.h | 1995 ++++++++++++++++++ src/cpu/core_dynrec/risc_mipsel32.h | 632 ++++++ src/cpu/core_dynrec/risc_x64.h | 598 ++++++ src/cpu/core_dynrec/risc_x86.h | 507 +++++ src/cpu/core_full/load.h | 5 - src/cpu/core_full/loadwrite.h | 1 - src/cpu/core_full/op.h | 46 +- src/cpu/core_normal/prefix_0f.h | 39 +- src/cpu/core_normal/prefix_66.h | 4 - src/cpu/core_normal/prefix_66_0f.h | 27 +- src/cpu/core_normal/prefix_none.h | 10 +- src/cpu/core_normal/support.h | 1 - src/cpu/cpu.cpp | 69 +- src/cpu/flags.cpp | 373 +++- src/cpu/instructions.h | 122 +- src/cpu/lazyflags.h | 14 +- src/debug/debug.cpp | 23 +- src/debug/debug_gui.cpp | 5 +- src/dos/cdrom.cpp | 2 +- src/dos/cdrom.h | 13 +- src/dos/cdrom_aspi_win32.cpp | 4 +- src/dos/cdrom_image.cpp | 10 +- src/dos/dev_con.h | 26 +- src/dos/dos.cpp | 65 +- src/dos/dos_classes.cpp | 14 +- src/dos/dos_devices.cpp | 8 +- src/dos/dos_files.cpp | 102 +- src/dos/dos_keyboard_layout.cpp | 2 +- src/dos/dos_memory.cpp | 2 +- src/dos/dos_mscdex.cpp | 23 +- src/dos/dos_programs.cpp | 229 +- src/dos/dos_tables.cpp | 13 +- src/dos/drive_cache.cpp | 6 +- src/dos/drive_fat.cpp | 9 +- src/dos/drive_iso.cpp | 14 +- src/dos/drive_local.cpp | 3 +- src/dos/drives.h | 4 +- src/dosbox.cpp | 10 +- src/gui/midi.cpp | 11 +- src/gui/midi_alsa.h | 6 +- src/gui/midi_coreaudio.h | 2 +- src/gui/midi_oss.h | 2 +- src/gui/midi_win32.h | 4 +- src/gui/render.cpp | 51 +- src/gui/render_scalers.cpp | 330 +-- src/gui/render_scalers.h | 36 +- src/gui/render_templates.h | 11 + src/gui/sdl_mapper.cpp | 171 +- src/gui/sdlmain.cpp | 61 +- src/hardware/fmopl.c | 84 +- src/hardware/gus.cpp | 59 +- src/hardware/iohandler.cpp | 16 +- src/hardware/keyboard.cpp | 11 +- src/hardware/memory.cpp | 28 +- src/hardware/mixer.cpp | 6 +- src/hardware/pcspeaker.cpp | 11 +- src/hardware/pic.cpp | 13 +- src/hardware/sblaster.cpp | 16 +- src/hardware/serialport/directserial_win32.h | 3 +- src/hardware/serialport/misc_util.cpp | 43 +- src/hardware/serialport/misc_util.h | 46 +- src/hardware/serialport/nullmodem.cpp | 2 + src/hardware/serialport/softmodem.cpp | 10 +- src/hardware/serialport/softmodem.h | 26 +- src/hardware/tandy_sound.cpp | 8 +- src/hardware/timer.cpp | 48 +- src/hardware/vga.cpp | 3 +- src/hardware/vga_dac.cpp | 3 + src/hardware/vga_draw.cpp | 10 +- src/hardware/vga_memory.cpp | 2 + src/hardware/vga_misc.cpp | 19 +- src/hardware/vga_s3.cpp | 9 +- src/hardware/vga_seq.cpp | 2 - src/hardware/ymf262.c | 84 +- src/ints/bios.cpp | 6 +- src/ints/bios_disk.cpp | 47 +- src/ints/int10.cpp | 18 +- src/ints/int10_char.cpp | 5 +- src/ints/int10_memory.cpp | 3 + src/ints/int10_misc.cpp | 4 +- src/ints/int10_modes.cpp | 113 +- src/ints/int10_pal.cpp | 4 +- src/ints/int10_put_pixel.cpp | 4 +- src/ints/int10_vesa.cpp | 4 +- src/ints/mouse.cpp | 91 +- src/ints/xms.cpp | 15 +- src/misc/programs.cpp | 11 +- src/misc/setup.cpp | 14 +- src/misc/support.cpp | 3 +- src/platform/visualc/config.h | 10 +- src/shell/shell.cpp | 20 +- src/shell/shell_batch.cpp | 14 +- src/shell/shell_cmds.cpp | 74 +- visualc_net/dosbox.vcproj | 31 + 142 files changed, 11913 insertions(+), 1384 deletions(-) create mode 100644 docs/PORTING create mode 100644 src/cpu/core_dynrec.cpp create mode 100644 src/cpu/core_dynrec/Makefile.am create mode 100644 src/cpu/core_dynrec/Makefile.in create mode 100644 src/cpu/core_dynrec/cache.h create mode 100644 src/cpu/core_dynrec/decoder.h create mode 100644 src/cpu/core_dynrec/decoder_basic.h create mode 100644 src/cpu/core_dynrec/decoder_opcodes.h create mode 100644 src/cpu/core_dynrec/dyn_fpu.h create mode 100644 src/cpu/core_dynrec/operators.h create mode 100644 src/cpu/core_dynrec/risc_mipsel32.h create mode 100644 src/cpu/core_dynrec/risc_x64.h create mode 100644 src/cpu/core_dynrec/risc_x86.h diff --git a/AUTHORS b/AUTHORS index 23121d5..c7f4622 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,8 +1,11 @@ The DOSBox Team --------------- -Sjoerd v.d. Berg -Peter Veenstra -Ulf Wohlers -Tommy Frössman -Dean Beeler +Sjoerd v.d. Berg +Peter Veenstra +Ulf Wohlers +Tommy Frössman +Dean Beeler +Sebastian Strohhäcker + +nick_without_<> @ users.sourceforge.net diff --git a/ChangeLog b/ChangeLog index 3573896..71da89c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,59 @@ +0.71 + - Add a new recompiling cpu core, which should be easier to port. + - Add 64 bit version of the recompiling core. + - Add mipsel 32 bit version of the recompiling core. + - Fix a few small problems with FCBs. (fixes Jewels of darkness and + cyrus chess) + - Raise some more exceptions. (fixes vbdos) + - Fix a few problems with the dynamic core. (fixes Inner Words, + Archmimedean Dynasty and others) + - Improve/Fix fallback code for certain graphics cards. + - Fix a few cd audio related bugs. + - Add an undocumented MSCDEX feature. (Fixes Ultimate Domain) + - Fix some pcspeaker mode. (fixes Test Drive and similar games) + - Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog) + - Remove Exit condition on fully nested mode. (fixes some demo) + - Add image file size detection. + - Add/Fix some ansi codes. (fixes PC Larn and certain versions of + infocom games) + - Several general DOS fixes. (fixes nba95, hexit and various other games) + - Add some valid input checks. (fixes 3d body adventure and similar + games) + - Fix digital joystick centering problem. + - Reenable textmode 54 and 55. + - Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General) + - Fix minor mixer underflow. + - Some general image and bios disk emulation fixes. + - Hopefully fix compilation on BSD and darwin. + - Try using ioctl cdrom access by default if possible. + - Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer + Teaches Chess) + - You can now close DOSBox using the status window in win32. + - Add support for NX enabled systems. + - Fix a casting error which only showed with certain compilers. (fixes + various games under mac os x and 64 bit linux) + - Improve timer and add gate 2 support. (fixes various games and + joystick problems) + - Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness, + PC-BLOX and others) + - Add/improve support for ~ and ~username in all commands. + - Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2) + - Change dma routine a bit. (fixes ticks in sound in various games) + - Allow read-only diskimages to be booted. (fixes various booter + games) + - Add basic hidden file support on cdrom images. (fixes Player + Manager 2) + - Add some rarely used functionality to the int10 mode setup. (fixes + WW2 Battles of the South pacific) + - Add ability to force scaler usage. + - Speed up flag generation and make it more 386-like. + - Some colourful feedback in the mapper. + - General code cleanup. + 0.70 - Improve register handling and support with XMS. - Fix some issues with deleting open files.(windows only issue) - - Add dummpy LPT1 class. (windows only issue) + - Add dummy LPT1 class. (windows only issue) - Improve some of the internal dos commands. (choice, copy and shift) - Improve ROM area. (for games that use it for random numbers or overwrite it as some sort of detection thing) @@ -13,7 +65,7 @@ - Move some interrupt handlers to XT Bios locations. - Add a dynamic fpu on x86. - Improve fpu on non-x86. - - Trapflag gets strickt priority over hardware IRQs. + - Trapflag gets strict priority over hardware IRQs. - Trapflag support for the dynamic core. - Add dummy TRx handling. - Fix a few rarely used character functions. diff --git a/INSTALL b/INSTALL index 56e6281..60ae267 100644 --- a/INSTALL +++ b/INSTALL @@ -41,24 +41,39 @@ 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 pause to enter the debugger. - ---disable-fpu - Will disable the emulated fpu. Although the fpu emulation code isn't - finished and isn't entirely accurate it's advised to leave it on. + window is active press alt-pause to enter the debugger. --enable-core-inline enables some memory increasing inlines. This greatly increases compiletime for maybe a increase in speed. ---disable-dynamic-x86 - disables the dynamic cpu core. Although it's unstable it can greatly - improve the speed of dosbox on x86 hosts. +--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. --disable-fpu-x86 disables the assembly fpu core. Although relatively new the x86 fpu core has more accuracy then 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. + 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. + +--disable-dynamic-core + disables all dynamic cores. (same effect as + --disable-dynamic-x86 --disable-dynrec) + +--disable-unaligned-memory + disables unaligned memory access. + Check the src subdir for the binary. NOTE: If capslock and numlock appear to be broken. open diff --git a/Makefile.in b/Makefile.in index c931043..602958d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -157,8 +157,8 @@ RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \ check-recursive installcheck-recursive DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/configure AUTHORS \ COPYING ChangeLog INSTALL Makefile.am NEWS THANKS acinclude.m4 \ - aclocal.m4 config.guess config.h.in config.sub configure \ - configure.in depcomp install-sh missing mkinstalldirs + aclocal.m4 config.guess config.h.in config.sub configure.in \ + depcomp install-sh missing mkinstalldirs DIST_SUBDIRS = $(SUBDIRS) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive diff --git a/NEWS b/NEWS index df85252..2291df1 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,59 @@ +0.71 + - Add a new recompiling cpu core, which should be easier to port. + - Add 64 bit version of the recompiling core. + - Add mipsel 32 bit version of the recompiling core. + - Fix a few small problems with FCBs. (fixes Jewels of darkness and + cyrus chess) + - Raise some more exceptions. (fixes vbdos) + - Fix a few problems with the dynamic core. (fixes Inner Words, + Archmimedean Dynasty and others) + - Improve/Fix fallback code for certain graphics cards. + - Fix a few cd audio related bugs. + - Add an undocumented MSCDEX feature. (Fixes Ultimate Domain) + - Fix some pcspeaker mode. (fixes Test Drive and similar games) + - Improve dos keyinput handling. (fixes Wing Commander 3 exit dialog) + - Remove Exit condition on fully nested mode. (fixes some demo) + - Add image file size detection. + - Add/Fix some ansi codes. (fixes PC Larn and certain versions of + infocom games) + - Several general DOS fixes. (fixes nba95, hexit and various other games) + - Add some valid input checks. (fixes 3d body adventure and similar + games) + - Fix digital joystick centering problem. + - Reenable textmode 54 and 55. + - Fix a pelmask problem with univbe 5.0 lite. (fixes Panzer General) + - Fix minor mixer underflow. + - Some general image and bios disk emulation fixes. + - Hopefully fix compilation on BSD and darwin. + - Try using ioctl cdrom access by default if possible. + - Fix some svga detection routine. (fixes Grandest Fleet 2 and Bobby Fischer + Teaches Chess) + - You can now close DOSBox using the status window in win32. + - Add support for NX enabled systems. + - Fix a casting error which only showed with certain compilers. (fixes + various games under mac os x and 64 bit linux) + - Improve timer and add gate 2 support. (fixes various games and + joystick problems) + - Improve mouse. Add undocumented backdoor. (fixes Last half of Darkness, + PC-BLOX and others) + - Add/improve support for ~ and ~username in all commands. + - Fix a font problem with the pcjr/tandy. (fixes personal deskmate 2) + - Change dma routine a bit. (fixes ticks in sound in various games) + - Allow read-only diskimages to be booted. (fixes various booter + games) + - Add basic hidden file support on cdrom images. (fixes Player + Manager 2) + - Add some rarely used functionality to the int10 mode setup. (fixes + WW2 Battles of the South pacific) + - Add ability to force scaler usage. + - Speed up flag generation and make it more 386-like. + - Some colourful feedback in the mapper. + - General code cleanup. + 0.70 - Improve register handling and support with XMS. - Fix some issues with deleting open files.(windows only issue) - - Add dummpy LPT1 class. (windows only issue) + - Add dummy LPT1 class. (windows only issue) - Improve some of the internal dos commands. (choice, copy and shift) - Improve ROM area. (for games that use it for random numbers or overwrite it as some sort of detection thing) @@ -13,7 +65,7 @@ - Move some interrupt handlers to XT Bios locations. - Add a dynamic fpu on x86. - Improve fpu on non-x86. - - Trapflag gets strickt priority over hardware IRQs. + - Trapflag gets strict priority over hardware IRQs. - Trapflag support for the dynamic core. - Add dummy TRx handling. - Fix a few rarely used character functions. diff --git a/README b/README index e1ed8f4..bc73d55 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -DOSBox v0.70 +DOSBox v0.71 ===== @@ -33,11 +33,18 @@ INDEX: 15. Contact + ============== 1. Quickstart: ============== -Type INTRO in DOSBox. That's it. +Type INTRO in DOSBox for a quick tour. +It is essential that you get familiar with the idea of mounting, +DOSBox does not automatically make any drive (or parts of it) +accessible to the emulation. +See the FAQ entry "I've got a Z instead of a C at the prompt" as +well as the description of the MOUNT command (section 4). + ======= @@ -47,24 +54,26 @@ Type INTRO in DOSBox. That's it. Some Frequently Asked Questions: Q: I've got a Z instead of a C at the prompt. -Q: How do I change to fullscreen ? +Q: Do I always have to type these commands? Automation? +Q: How do I change to fullscreen? Q: My CD-ROM doesn't work. Q: The mouse doesn't work. Q: There is no sound. Q: The sound stutters or sounds stretched/weird. Q: I can't type \ or : in DOSBox. +Q: The keyboard lags. +Q: The cursor always moves into one direction! Q: The game/application can't find its CD-ROM. Q: The game/application runs much too slow! Q: Can DOSBox harm my computer? Q: I would like to change the memory size/cpu speed/ems/soundblaster IRQ. Q: What sound hardware does DOSBox presently emulate? -Q: DOSBox crashes on startup and I'm running arts +Q: DOSBox crashes on startup and I'm running arts. Q: Great README, but I still don't get it. - Q: I've got a Z instead of a C at the prompt. A: You have to make your directories available as drives in DOSBox by using the "mount" command. For example, in Windows "mount C D:\GAMES" will give @@ -75,7 +84,13 @@ A: You have to make your directories available as drives in DOSBox by using fine, DOSBox will display the prompt "C:\>". -Q: How do I change to fullscreen ? +Q: Do I always have to type these commands? Automation? +A: In the DOSBox configuration file is an [autoexec] section. The commands + present there are run when DOSBox starts, so you can use this section + for the mounting. + + +Q: How do I change to fullscreen? A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and change the option fullscreen=false to fullscreen=true. If fullscreen looks wrong in your opinion: Play with the option fullresolution in the @@ -86,17 +101,17 @@ A: Press alt-enter. Alternatively: Edit the configuration file of DOSBox and Q: My CD-ROM doesn't work. A: To mount your CD-ROM in DOSBox you have to specify some additional options when mounting the CD-ROM. - To enable the most basic CD-ROM support: + To enable CD-ROM support (includes MSCDEX): - mount d f:\ -t cdrom - To enable low-level SDL-support: + To enable low-level CD-ROM-support (uses ioctl if possible): - mount d f:\ -t cdrom -usecd 0 - To enable low-level ioctl-support(win2k/xp/linux): - - mount d f:\ -t cdrom -usecd 0 -ioctl + To enable low-level SDL-support: + - mount d f:\ -t cdrom -usecd 0 -noioctl To enable low-level aspi-support (win98 with aspi-layer installed): - mount d f:\ -t cdrom -usecd 0 -aspi In the commands: - d driveletter you will get in DOSBox - - f:\ location of cdrom on your PC. + - f:\ location of CD-ROM on your PC. - 0 The number of the CD-ROM drive, reported by mount -cd See also the question: The game/application can't find its CD-ROM. @@ -123,11 +138,12 @@ A: Be sure that the sound is correctly configured in the game. This might be Q: The sound stutters or sounds stretched/weird. -A: You're using too much cpu power to keep DOSBox running at the current speed. - You can lower the cycles, skip frames or get a faster machine. - You can also increase the prebuffer in the configfile. +A: You're using too much CPU power to keep DOSBox running at the current speed. + You can lower the cycles, skip frames, reduce the sampling rate of + the respective sound device (see the DOSBox configuration file) or + the mixer device. You can also increase the prebuffer in the configfile. If you are using cycles=max or =auto, then make sure that there no - background processes interfering! (especially if they acces the harddisk) + background processes interfering! (especially if they access the harddisk) Q: I can't type \ or : in DOSBox. @@ -137,7 +153,7 @@ A: This is a known problem. It only occurs if your keyboard layout isn't US. 2. Use / instead. 3. Open dosbox.conf and change usescancodes=false to usescancodes=true. 4. Add the commands you want to execute to the "configfile". - 5. Change the dos keyboard layout (see Section 7 Keyboard Layout). + 5. Change the DOS keyboard layout (see Section 7 Keyboard Layout). 6. Use ALT-58 for : and ALT-92 for \. 7. for \ try the keys around "enter". For ":" try shift and the keys between "enter" and "l" (US keyboard layout). @@ -146,14 +162,32 @@ A: This is a known problem. It only occurs if your keyboard layout isn't US. have a bug in the loader routines. +Q: The keyboard lags. +A: Lower the priority setting in the DOSBox configuration file + like set "priority=normal,normal". You might also want to + try lowering the cycles. + + +Q: The cursor always moves into one direction! +A: See if it still happens if you disable the joystick emulation, + set joysticktype=none in the [joystick] section of your DOSBox + configuration file. Maybe also try unplugging any joystick. + If you want to use the joystick in the game, try setting timed=false + and be sure to calibrate the joystick (both in your OS as well as + in the game or the game's setup). + + Q: The game/application can't find its CD-ROM. A: Be sure to mount the CD-ROM with -t cdrom switch, this will enable the MSCDEX interface required by DOS games to interface with CD-ROMs. Also try adding the correct label (-label LABEL). To enable lower-level CD-ROM support, add the following switch to mount: -usecd #, where # is the number of your CD-ROM drive reported by mount -cd. Under Windows you - can specify -ioctl or -aspi. Look at the description elsewhere in this - document for their meaning. + can specify -ioctl, -aspi or -noioctl. Look at the description elsewhere + in this document for their meaning. + Try creating a CD-ROM image (preferably CUE/BIN pair) and use the + DOSBox-internal IMGMOUNT tool to mount the image. This enables very + good low-level CD-ROM support on any operating system. Q: The game/application runs much too slow! @@ -217,7 +251,7 @@ A: This isn't really a DOSBox problem, but the solution is to set the Q: Great README, but I still don't get it. A: A look at "The Newbie's pictorial guide to DOSBox" located at http://vogons.zetafleet.com/viewforum.php?f=39 might help you. - Also try the wiki of dosbox: + Also try the wiki of DOSBox: http://dosbox.sourceforge.net/wiki/ @@ -227,7 +261,6 @@ http://dosbox.sourceforge.net - ========= 3. Usage: ========= @@ -240,7 +273,7 @@ description: dosbox [name] [-exit] [-c command] [-fullscreen] [-conf congfigfile] [-lang languagefile] [-machine machinetype] [-noconsole] - [-startmapper] [-noautoexec] + [-startmapper] [-noautoexec] [-scaler scaler | -forcescaler scaler] dosbox -version @@ -269,15 +302,15 @@ dosbox -version -lang languagefile Start DOSBox using the language specified in "languagefile". - -noconsole (Windows Only) - Start DOSBox without showing the console window. Output will - be redirected to stdout.txt and stderr.txt - -machine machinetype Setup DOSBox to emulate a specific type of machine. Valid choices are: hercules, cga, pcjr, tandy, vga (default). The machinetype affects both the videocard and the available soundcards. + -noconsole (Windows Only) + Start DOSBox without showing the console window. Output will + be redirected to stdout.txt and stderr.txt + -startmapper Enter the keymapper directly on startup. Useful for people with keyboard problems. @@ -285,6 +318,14 @@ dosbox -version -noautoexec Skips the [autoexec] section of the loaded configuration file. + -scaler scaler + Uses the scaler specified by "scaler". See the DOSBox configuration + file for the available scalers. + + -forcescaler scaler + Similar to the -scaler parameter, but tries to force usage of + the specified scaler even if it might not fit. + -version output version information and exit. Useful for frontends. @@ -318,35 +359,44 @@ To get a list of the internal commands type "HELP" at the prompt. In addition, the following commands are available: MOUNT "Emulated Drive letter" "Real Drive or Directory" - [-t type] [-aspi] [-ioctl] [-usecd number] [-size drivesize] + [-t type] [-aspi] [-ioctl] [-noioctl] [-usecd number] [-size drivesize] [-label drivelabel] [-freesize size_in_mb] + [-freesize size_in_kb (floppies)] MOUNT -cd MOUNT -u "Emulated Drive letter" Program to mount local directories as drives inside DOSBox. "Emulated Drive letter" - The driveletter inside dosbox (eg. C). + The driveletter inside DOSBox (eg. C). "Real Drive letter (usually for CD-ROMs in Windows) or Directory" - The local directory you want accessible inside dosbox. + The local directory you want accessible inside DOSBox. -t type Type of the mounted directory. Supported are: dir (default), floppy, cdrom. -size drivesize - Sets the size of the drive. + Sets the size of the drive, where drivesize is of the form + "bps,spc,tcl,fcl": + bps: bytes per sector, by default 512 for regular drives and + 2048 for CD-ROM drives + spc: sectors per cluster, usually between 1 and 127 + tcl: total clusters, between 1 and 65534 + fcl: total free clusters, between 1 and tcl - -freesize size_in_mb - Sets the amount of free space available on a drive in megabytes. + -freesize size_in_mb | size_in_kb + Sets the amount of free space available on a drive in megabytes + (regular drives) or kilobytes (floppy drives). This is a simpler version of -size. -label drivelabel Sets the name of the drive to "drivelabel". Needed on some systems if the cd label isn't read correctly. Useful when a - program can't find its cdrom. If you don't specify a label and no - lowlevel support is selected (-usecd # and/or -ioctl/aspi): + program can't find its CD-ROM. If you don't specify a label and no + lowlevel support is selected (that is omitting the -usecd # and/or + -aspi parameters or specifying -noioctl): For win32: label is extracted from "Real Drive". For Linux: label is set to NO_LABEL. @@ -354,24 +404,27 @@ MOUNT -u "Emulated Drive letter" is mounted. It will not be updated !! -aspi - Forces use of the aspi layer. Only valid if mounting a cdrom under + Forces use of the aspi layer. Only valid if mounting a CD-ROM under Windows systems with an ASPI-Layer. -ioctl - Forces use of ioctl commands. Only valid if mounting a cdrom under + Forces use of ioctl commands. Only valid if mounting a CD-ROM under a Windows OS which support them (Win2000/XP/NT). + -noioctl + Forces use of the SDL CD-ROM layer. Valid on all systems. + -usecd number - Forces use of SDL cdrom support for drive number. + Forces use of SDL CD-ROM support for drive number. Number can be found by -cd. Valid on all systems. -cd - Displays all detected cdrom drives and their numbers. Use with -usecd. + Displays all detected CD-ROM drives and their numbers. Use with -usecd. -u Removes the mount. Doesn't work for Z:\. - Note: It's possible to mount a local directory as cdrom drive. + Note: It's possible to mount a local directory as CD-ROM drive. Hardware support is then missing. Basically MOUNT allows you to connect real hardware to DOSBox's emulated PC. @@ -387,7 +440,7 @@ MOUNT -u "Emulated Drive letter" Mounting your entire C drive with MOUNT C C:\ is NOT recommended! The same is true for mounting the root of any other drive, except for CD-ROMs (due to - their read-only nature). Otherwise if you or DOSBox make a mistakes you may + their read-only nature). Otherwise if you or DOSBox make a mistake you may loose all your files. It is recommended to put all your applications/games into a subdirectory and mount that. @@ -395,24 +448,27 @@ MOUNT -u "Emulated Drive letter" General MOUNT Examples: 1. To mount c:\DirX as a floppy : mount a c:\DirX -t floppy - 2. To mount system cdrom drive E as cdrom drive D in DOSBox: + 2. To mount system CD-ROM drive E as CD-ROM drive D in DOSBox: mount d e:\ -t cdrom - 3. To mount system cdrom drive at mountpoint /media/cdrom as cdrom drive D - in dosbox: + 3. To mount system CD-ROM drive at mountpoint /media/cdrom as CD-ROM drive D + in DOSBox: mount d /media/cdrom -t cdrom -usecd 0 - 4. To mount a drive with 870 mb free diskspace (simple version): + 4. To mount a drive with ~870 mb free diskspace (simple version): mount c d:\ -freesize 870 - 5. To mount a drive with 870 mb free diskspace (experts only, full control): - mount c d:\ -size 4025,127,16513,1700 + 5. To mount a drive with ~870 mb free diskspace (experts only, full control): + mount c d:\ -size 512,127,16513,13500 6. To mount /home/user/dirY as drive C in DOSBox: mount c /home/user/dirY + 7. To mount the directory where DOSBox was started as D in DOSBox: + mount d . MEM Program to display the amount of free memory. -CONFIG [-writeconf] [-writelang] localfile +CONFIG -writeconf localfile +CONFIG -writelang localfile CONFIG -set "section property=value" CONFIG -get "section property" @@ -432,8 +488,8 @@ CONFIG -get "section property" -writelang localfile Write the current language settings to file. "localfile" is located on the local drive, not a mounted drive in DOSBox. - The language file controls all visible ouput of the internal commands - and the internal dos. + The language file controls all visible output of the internal commands + and the internal DOS. -set "section property=value" CONFIG will attempt to set the property to new value. At this moment @@ -469,7 +525,6 @@ LOADFIX -f -f frees all previously allocated memory - Examples: 1. To start mm2.exe and allocate 64kb memory (mm2 will have 64 kb less available) : @@ -496,14 +551,14 @@ MIXER left:right The volume levels in percentages. If you put a D in front it will be - in deciBell (example mixer gus d-10). + in decibel (example mixer gus d-10). /NOSHOW Prevents DOSBox from showing the result if you set one of the volume levels. /LISTMIDI - Lists the available midi devices on your pc (Windows). To select a + Lists the available midi devices on your PC (Windows). To select a device other than the Windows default midi-mapper, add a line 'config=id' to the [midi] section in the configuration file, where 'id' is the number for the device as listed by LISTMIDI. @@ -632,7 +687,7 @@ IPX IPXNET STARTSERVER - IPXNET STARTSERVER starts and IPX tunneling server on this DOSBox + IPXNET STARTSERVER starts an IPX tunnelling server on this DOSBox session. By default, the server will accept connections on UDP port 213, though this can be changed. Once the server is started, DOSBox will automatically start a client connection to the IPX tunnelling server. @@ -712,7 +767,6 @@ For more information use the /? command line switch with the programs. - ================ 5. Special Keys: ================ @@ -728,7 +782,7 @@ CTRL-ALT-F7 Start/Stop recording of OPL commands. CTRL-ALT-F8 Start/Stop the recording of raw MIDI commands. CTRL-F7 Decrease frameskip. CTRL-F8 Increase frameskip. -CTRL-F9 Kill dosbox. +CTRL-F9 Kill DOSBox. CTRL-F10 Capture/Release the mouse. CTRL-F11 Slow down emulation (Decrease DOSBox Cycles). CTRL-F12 Speed up emulation (Increase DOSBox Cycles). @@ -811,9 +865,9 @@ Examples about remapping the joystick: You have a joystick attached, it is working fine under DOSBox and you want to play some keyboard-only game with the joystick (it is assumed that the game is controlled by the arrows on the keyboard): - 1) Start the mapper, then klick on one of the arrows in the middle + 1) Start the mapper, then click on one of the arrows in the middle of the left part of the screen (right above the Mod1/Mod2 buttons). - EVENT should be key_left. Now klick on Add and move your joystick + EVENT should be key_left. Now click on Add and move your joystick in the respective direction, this should add an event to the BIND. 2) Repeat the above for the missing three directions, additionally the buttons of the joystick can be remapped as well (fire/jump). @@ -822,12 +876,12 @@ Examples about remapping the joystick: You want to swap the y-axis of the joystick because some flightsim uses the up/down joystick movement in a way you don't like, and it is not configurable in the game itself: - 1) Start the mapper and klick on Y- in the upper joystick field (this + 1) Start the mapper and click on Y- in the upper joystick field (this is for the first joystick if you have two joysticks attached) or the lower joystick field (second joystick or, if you have only one joystick attached, the second axes cross). EVENT should be jaxis_0_1- (or jaxis_1_1-). - 2) Click on Del to remove the current binding, then klick Add and move + 2) Click on Del to remove the current binding, then click Add and move your joystick downwards. A new bind should be created. 3) Repeat this for Y+, save the layout and finally test it with some game. @@ -845,8 +899,8 @@ is present in the configfile. =================== To switch to a different keyboard layout, either the entry "keyboardlayout" -in the [dos]-section in dosbox.conf can be used, or the internal DOSBox -program keyb.com. Both accept dos-conform language codes (see below), but +in the [dos] section in dosbox.conf can be used, or the internal DOSBox +program keyb.com. Both accept DOS conforming language codes (see below), but only by using keyb.com a custom codepage can be specified. Layout switching @@ -861,10 +915,8 @@ Layout switching NO (Norway), PL (Poland), RU (Russian Federation), SK (Slovakia), SP (Spain), SU (Finland), SV (Sweden) - When a keyboard layout is loaded, it is possible to switch between the - foreign layout and the US-layout by pressing CTRL+ALT+F2. Some keyboard layouts (for example layout GK codepage 869 and layout RU - codepage 808) have support for dual-layouts that can be activated by + codepage 808) have support for dual layouts that can be activated by pressing LEFT-ALT+RIGHT-SHIFT and deactivated by LEFT-ALT+LEFT-SHIFT. Supported external files @@ -874,12 +926,12 @@ Supported external files See http://projects.freedos.net/keyb/ for precompiled keyboard layouts. Both .CPI (MSDOS/compatible codepage files) and .CPX (freedos UPX-compressed - codepage files) can be used. Some codepages are compiled into DOSBox so it + codepage files) can be used. Some codepages are compiled into DOSBox, so it is mostly not needed to care about external codepage files. If you need a different (or custom) codepage file, copy it into the directory of the DOSBox configuration file so it is accessible for DOSBox. - Additional layouts can be added by copying the corresponding .kl-file into + Additional layouts can be added by copying the corresponding .kl file into the directory of dosbox.conf and using the first part of the filename as language code. Example: For the file UZ.KL (keyboard layout for Uzbekistan) specify @@ -925,7 +977,7 @@ of the nullmodem connection. These are all parameters: * server: - This nullmodem will be a client connecting to the specified server. (No server argument: be a server.) * transparent:1 - Only send the serial data, no RTS/DTR handshake. Use this - when connecting to anyting other than a nullmodem. + when connecting to anything other than a nullmodem. * telnet:1 - Interpret Telnet data from the remote site. Automatically sets transparent. * usedtr:1 - The connection will not be established until DTR is switched @@ -957,7 +1009,7 @@ CPU Cycles at the top then. In this mode you can reduce the amount of cycles on a percentage-basis (hit CTRL-F11) or raise it again (CTRL-F12). - Sometimes customly setting the number of cycles achieves better results, + Sometimes manually setting the number of cycles achieves better results, in the DOSBox configuration file specify for example cycles=30000. When running some DOS application you can raise the cycles with CTRL-F12 even more, but you will be limited by the power of your actual CPU. You can see @@ -992,14 +1044,14 @@ as possible for DOSBox. Advanced cycles configuration: -The cycles=auto and cycles=max settings can be parametrized to have +The cycles=auto and cycles=max settings can be parameterized to have different startup defaults. The syntax is cycles=auto ["realmode default"] ["protected mode default"%] [limit "cycle limit"] cycles=max ["protected mode default"%] [limit "cycle limit"] Example: cycles=auto 1000 80% limit 20000 - will use cycles=1000 for real mode games, 80% cpu throttling for + will use cycles=1000 for real mode games, 80% CPU throttling for protected mode games along with a hard cycle limit of 20000 @@ -1018,7 +1070,7 @@ Running a certain game closes DOSBox, crashes with some message or hangs: (unmodified configuration file) - try it with sound disabled (use the sound configuration program that comes with the game, additionally you can - use sbtype=none and gus=false) + set sbtype=none and gus=false in the DOSBox configuration file) - change some entries of the DOSBox configuration file, especially try: core=normal fixed cycles (for example cycles=10000) @@ -1033,18 +1085,21 @@ The game exits to the DOSBox prompt with some error message: - mount differently as some games are picky about the locations, for example if you used "mount d d:\oldgames\game" try "mount c d:\oldgames\game" and "mount c d:\oldgames" - - if the game requires a cdrom be sure you used "-t cdrom" when - mounting and try different additional parameters + - if the game requires a CD-ROM be sure you used "-t cdrom" when + mounting and try different additional parameters (the ioctl, + usecd and label switches, see the appropriate section) - check the file permissions of the game files (remove read-only attributes, add write permissions etc.) - - try reinstalling the game within dosbox + - try reinstalling the game within DOSBox + + ==================== 11. The Config File: ==================== A config file can be generated by CONFIG.COM, which can be found on the -internal dosbox Z: drive when you start up dosbox. Look in the internal +internal DOSBox Z: drive when you start up DOSBox. Look in the internal programs section of the readme for usage of CONFIG.COM. You can edit the generated configfile to customize DOSBox. @@ -1066,7 +1121,7 @@ look in the current directory for dosbox.conf. 12. The Language File: ====================== -A language file can be generated by CONFIG.COM. +A language file can be generated by CONFIG.COM (CONFIG -writelang langfile). Read it, and you will hopefully understand how to change it. Start DOSBox with the -lang switch to use your new language file. Alternatively, you can setup the filename in the config file in the [dosbox] @@ -1087,17 +1142,7 @@ Check the INSTALL in the source distribution. 14. Special thanks: =================== -Vlad R. of the VDMSound project for excellent SoundBlaster info. -Tatsuyuki Satoh of the Mame Team for making an excellent FM emulator. -The Bochs and DOSemu projects, which I used for information. -Freedos for ideas in making my shell. -Pierre-Yves Gérardy for hosting the old Beta Board. -Colin Snover for hosting our forum. -Jantien for the version management. -Shawn and Johannes for creating the MAC OS X PPC version. -Ido Beeri for the icon. -The Beta Testers. - +See the THANKS file. ============ diff --git a/THANKS b/THANKS index d48a61d..7698f02 100644 --- a/THANKS +++ b/THANKS @@ -12,11 +12,14 @@ Pierre-Yves G Colin Snover for hosting our forum. Sourceforge for hosting our homepage and other development tools. -Mirek Luza for his moderation of the forums. -c2woody for his debug work. +Mirek Luza, for his moderation of the forums. +eL_Pusher, DosFreak and MiniMax for their moderation of VOGONS forum. + +crazyc and gulikoza for their work on the dynrec core. Jantien for the version management. -Shawn and Johannes for creating the MAC OS X PPC version. +Shawn, Johannes and Marcus for creating the MAC OS X version. +Jochen for creating the OS/2 version. Ido Beeri for the icon. All the people who submitted a bug. The Beta Testers. diff --git a/config.guess b/config.guess index c38553d..396482d 100644 --- a/config.guess +++ b/config.guess @@ -1,9 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. -timestamp='2006-02-23' +timestamp='2006-07-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -210,7 +211,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) - echo powerppc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} @@ -770,6 +771,8 @@ EOF case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac @@ -780,9 +783,6 @@ EOF i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS_NT-*:*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 @@ -790,10 +790,10 @@ EOF i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - x86:Interix*:[345]*) + x86:Interix*:[3456]*) echo i586-pc-interix${UNAME_RELEASE} exit ;; - EM64T:Interix*:[345]*) + EM64T:Interix*:[3456]*) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) @@ -831,6 +831,9 @@ EOF arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; @@ -989,7 +992,7 @@ EOF LIBC=gnulibc1 # endif #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun) + #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) LIBC=gnu #else LIBC=gnuaout diff --git a/config.h.in b/config.h.in index 44c5135..b843234 100644 --- a/config.h.in +++ b/config.h.in @@ -33,6 +33,10 @@ /* Define to 1 to use x86 dynamic cpu core */ #undef C_DYNAMIC_X86 +/* Define to 1 to use recompiling cpu core. Can not be used together with the + dynamic-x86 core */ +#undef C_DYNREC + /* Define to 1 to enable floating point emulation */ #undef C_FPU @@ -52,9 +56,6 @@ /* Define to 1 to enable heavy debugging, also have to enable C_DEBUG */ #undef C_HEAVY_DEBUG -/* The type of cpu this host has */ -#undef C_HOSTCPU - /* Define to 1 to enable IPX over Internet networking, requires SDL_net */ #undef C_IPX @@ -73,6 +74,9 @@ /* Define to 1 to enable screenshots, requires libpng */ #undef C_SSHOT +/* The type of cpu this target has */ +#undef C_TARGETCPU + /* Define to 1 to use a unaligned memory access */ #undef C_UNALIGNED_MEMORY @@ -103,6 +107,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H @@ -115,6 +125,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H @@ -124,7 +137,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Compiling on GNU/Linux */ +/* Compiling on GNU/Linux or *BSD */ #undef LINUX /* Compiling on Mac OS X */ @@ -194,6 +207,9 @@ /* Define to `unsigned int' if does not define. */ #undef size_t +/* Define to `int` if you don't have socklen_t */ +#undef socklen_t + #define INLINE inline #if C_HAS_ATTRIBUTE diff --git a/config.sub b/config.sub index ad9f395..387c18d 100644 --- a/config.sub +++ b/config.sub @@ -1,9 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, +# Inc. -timestamp='2006-02-23' +timestamp='2006-07-02' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -240,7 +241,7 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ @@ -248,7 +249,8 @@ case $basic_machine in | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ - | m32r | m32rle | m68000 | m68k | m88k | maxq | mb | microblaze | mcore \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -274,11 +276,11 @@ case $basic_machine in | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ - | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ - | sparcv8 | sparcv9 | sparcv9b \ - | strongarm \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ @@ -286,9 +288,6 @@ case $basic_machine in | z8k) basic_machine=$basic_machine-unknown ;; - m32c) - basic_machine=$basic_machine-unknown - ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown @@ -318,7 +317,7 @@ case $basic_machine in | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ - | avr-* \ + | avr-* | avr32-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | craynv-* | cydra-* \ @@ -329,7 +328,7 @@ case $basic_machine in | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ - | m32r-* | m32rle-* \ + | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ @@ -358,11 +357,11 @@ case $basic_machine in | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ @@ -373,8 +372,6 @@ case $basic_machine in | ymp-* \ | z8k-*) ;; - m32c-*) - ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) @@ -1128,7 +1125,7 @@ case $basic_machine in sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b) + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) @@ -1217,7 +1214,7 @@ case $os in | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos*) + | -skyos* | -haiku* | -rdos* | -toppers*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1369,6 +1366,9 @@ else # system, and we'll never get to this point. case $basic_machine in + spu-*) + os=-elf + ;; *-acorn) os=-riscix1.2 ;; @@ -1378,9 +1378,9 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff - ;; + c4x-* | tic4x-*) + os=-coff + ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 diff --git a/configure b/configure index 7cc6d1b..75aeff9 100644 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.60a for dosbox 0.70. +# Generated by GNU Autoconf 2.60a for dosbox 0.71. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -557,8 +557,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='dosbox' PACKAGE_TARNAME='dosbox' -PACKAGE_VERSION='0.70' -PACKAGE_STRING='dosbox 0.70' +PACKAGE_VERSION='0.71' +PACKAGE_STRING='dosbox 0.71' PACKAGE_BUGREPORT='' ac_unique_file="README" @@ -1215,7 +1215,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures dosbox 0.70 to adapt to many kinds of systems. +\`configure' configures dosbox 0.71 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1286,7 +1286,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of dosbox 0.70:";; + short | recursive ) echo "Configuration of dosbox 0.71:";; esac cat <<\_ACEOF @@ -1296,10 +1296,13 @@ Optional Features: --disable-dependency-tracking Speeds up one-time builds --enable-dependency-tracking Do not reject slow dependency extractors --disable-sdltest Do not try to compile and run a test SDL program + --enable-alsa-midi compile with alsa midi support (default yes) --disable-alsatest Do not try to compile and run a test Alsa program --enable-debug Enable debug mode --enable-core-inline Enable inlined memory handling in CPU Core + --disable-dynamic-core Disable all dynamic cores --disable-dynamic-x86 Disable x86 dynamic cpu core + --disable-dynrec Disable recompiling cpu core --disable-fpu Disable fpu support --disable-fpu-x86 Disable x86 assembly fpu core --disable-unaligned-memory @@ -1388,7 +1391,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -dosbox configure 0.70 +dosbox configure 0.71 generated by GNU Autoconf 2.60a Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1402,7 +1405,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by dosbox $as_me 0.70, which was +It was created by dosbox $as_me 0.71, which was generated by GNU Autoconf 2.60a. Invocation command line was $ $0 $@ @@ -2170,7 +2173,7 @@ fi # Define the identity of the package. PACKAGE='dosbox' - VERSION='0.70' + VERSION='0.71' cat >>confdefs.h <<_ACEOF @@ -8693,6 +8696,328 @@ _ACEOF + + +for ac_header in stdlib.h sys/types.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +for ac_header in sys/socket.h netinet/in.h pwd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif + + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Header=no" +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +cat >conftest.$ac_ext <<_ACEOF + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +cat >>confdefs.h <<\_ACEOF +#define socklen_t int +_ACEOF + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + { echo "$as_me:$LINENO: checking if environ can be included" >&5 echo $ECHO_N "checking if environ can be included... $ECHO_C" >&6; } cat >conftest.$ac_ext <<_ACEOF @@ -9156,7 +9481,18 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -alsa_save_CFLAGS="$CFLAGS" +# Check whether --enable-alsa-midi was given. +if test "${enable_alsa_midi+set}" = set; then + enableval=$enable_alsa_midi; case "${enableval}" in + yes) alsa_midi=true;; + no) alsa_midi=false;; +esac +else + alsa_midi=true +fi + +if test x$alsa_midi = xtrue ; then + alsa_save_CFLAGS="$CFLAGS" alsa_save_LDFLAGS="$LDFLAGS" alsa_save_LIBS="$LIBS" alsa_found=yes @@ -9448,6 +9784,8 @@ fi + CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS" +fi #Check for big endian machine, should #define WORDS_BIGENDIAN if so { echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 @@ -10121,39 +10459,49 @@ fi { echo "$as_me:$LINENO: checking for target cpu type" >&5 echo $ECHO_N "checking for target cpu type... $ECHO_C" >&6; } case "$target_cpu" in + x86_64 | amd64) + cat >>confdefs.h <<\_ACEOF +#define C_TARGETCPU X86_64 +_ACEOF + + { echo "$as_me:$LINENO: result: x86-64 bit compatible" >&5 +echo "${ECHO_T}x86-64 bit compatible" >&6; } + c_targetcpu="x86_64" + c_unalignedmemory=yes + ;; i?86) cat >>confdefs.h <<\_ACEOF -#define C_HOSTCPU X86 +#define C_TARGETCPU X86 _ACEOF { echo "$as_me:$LINENO: result: x86 compatible" >&5 echo "${ECHO_T}x86 compatible" >&6; } - c_hostcpu="x86" + c_targetcpu="x86" c_unalignedmemory=yes ;; powerpc*) cat >>confdefs.h <<\_ACEOF -#define C_HOSTCPU POWERPC +#define C_TARGETCPU POWERPC _ACEOF { echo "$as_me:$LINENO: result: Power PC" >&5 echo "${ECHO_T}Power PC" >&6; } - c_hostcpu="powerpc" + c_targetcpu="powerpc" c_unalignedmemory=yes ;; m68k*) cat >>confdefs.h <<\_ACEOF -#define C_HOSTCPU M68K +#define C_TARGETCPU M68K _ACEOF { echo "$as_me:$LINENO: result: Motorola 68000" >&5 echo "${ECHO_T}Motorola 68000" >&6; } - c_hostcpu="m68k" + c_targetcpu="m68k" c_unalignedmemory=yes ;; *) cat >>confdefs.h <<\_ACEOF -#define C_HOSTCPU UNKOWN +#define C_TARGETCPU UNKNOWN _ACEOF { echo "$as_me:$LINENO: result: unknown" >&5 @@ -10162,6 +10510,14 @@ echo "${ECHO_T}unknown" >&6; } ;; esac +# Check whether --enable-dynamic-core was given. +if test "${enable_dynamic_core+set}" = set; then + enableval=$enable_dynamic_core; +else + enable_dynamic_core=yes +fi + + # Check whether --enable-dynamic-x86 was given. @@ -10173,11 +10529,11 @@ fi { echo "$as_me:$LINENO: checking whether x86 dynamic cpu core will be enabled" >&5 echo $ECHO_N "checking whether x86 dynamic cpu core will be enabled... $ECHO_C" >&6; } -if test x$enable_dynamic_x86 = xno ; then +if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } else - if test x$c_hostcpu = xx86 ; then + if test x$c_targetcpu = xx86 ; then cat >>confdefs.h <<\_ACEOF #define C_DYNAMIC_X86 1 _ACEOF @@ -10192,6 +10548,48 @@ fi +# Check whether --enable-dynrec was given. +if test "${enable_dynrec+set}" = set; then + enableval=$enable_dynrec; +else + enable_dynrec=yes +fi + +{ echo "$as_me:$LINENO: checking whether recompiling cpu core will be enabled" >&5 +echo $ECHO_N "checking whether recompiling cpu core will be enabled... $ECHO_C" >&6; } +if test x$enable_dynrec = xno -o x$enable_dynamic_core = xno; then + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +else + if test x$c_targetcpu = xx86 ; then + if test x$enable_dynamic_x86 = xno ; then + cat >>confdefs.h <<\_ACEOF +#define C_DYNREC 1 +_ACEOF + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no, using dynamic-x86" >&5 +echo "${ECHO_T}no, using dynamic-x86" >&6; } + fi + else + if test x$c_targetcpu = xx86_64 ; then + cat >>confdefs.h <<\_ACEOF +#define C_DYNREC 1 +_ACEOF + + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } + fi + fi +fi + + + # Check whether --enable-fpu was given. if test "${enable_fpu+set}" = set; then enableval=$enable_fpu; @@ -10229,7 +10627,7 @@ if test x$enable_fpu_x86 = xno ; then echo "${ECHO_T}no" >&6; } else if test x$enable_fpu = xyes; then - if test x$c_hostcpu = xx86 ; then + if test x$c_targetcpu = xx86 ; then cat >>confdefs.h <<\_ACEOF #define C_FPU_X86 1 _ACEOF @@ -10845,28 +11243,7 @@ fi -# Check whether --enable-opengl was given. -if test "${enable_opengl+set}" = set; then - enableval=$enable_opengl; -else - enable_opengl=yes -fi - -{ echo "$as_me:$LINENO: checking whether opengl display output will be enabled" >&5 -echo $ECHO_N "checking whether opengl display output will be enabled... $ECHO_C" >&6; } -if test x$enable_opengl = xyes; then -case "$target" in - *-*-darwin*) - { echo "$as_me:$LINENO: result: yes" >&5 -echo "${ECHO_T}yes" >&6; } - LIBS="$LIBS -framework OpenGL" - cat >>confdefs.h <<\_ACEOF -#define C_OPENGL 1 -_ACEOF - - ;; - *) - { echo "$as_me:$LINENO: checking for main in -lGL" >&5 +{ echo "$as_me:$LINENO: checking for main in -lGL" >&5 echo $ECHO_N "checking for main in -lGL... $ECHO_C" >&6; } if test "${ac_cv_lib_GL_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -10943,7 +11320,7 @@ else have_gl_lib=no fi - { echo "$as_me:$LINENO: checking for main in -lopengl32" >&5 +{ echo "$as_me:$LINENO: checking for main in -lopengl32" >&5 echo $ECHO_N "checking for main in -lopengl32... $ECHO_C" >&6; } if test "${ac_cv_lib_opengl32_main+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -11020,7 +11397,7 @@ else have_opengl32_lib=no fi - if test "${ac_cv_header_GL_gl_h+set}" = set; then +if test "${ac_cv_header_GL_gl_h+set}" = set; then { echo "$as_me:$LINENO: checking for GL/gl.h" >&5 echo $ECHO_N "checking for GL/gl.h... $ECHO_C" >&6; } if test "${ac_cv_header_GL_gl_h+set}" = set; then @@ -11176,6 +11553,27 @@ else fi +# Check whether --enable-opengl was given. +if test "${enable_opengl+set}" = set; then + enableval=$enable_opengl; +else + enable_opengl=yes +fi + +{ echo "$as_me:$LINENO: checking whether opengl display output will be enabled" >&5 +echo $ECHO_N "checking whether opengl display output will be enabled... $ECHO_C" >&6; } +if test x$enable_opengl = xyes; then +case "$target" in + *-*-darwin*) + { echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6; } + LIBS="$LIBS -framework OpenGL" + cat >>confdefs.h <<\_ACEOF +#define C_OPENGL 1 +_ACEOF + + ;; + *) if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then { echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6; } @@ -12043,7 +12441,7 @@ _ACEOF LIBS="$LIBS -framework AudioUnit" ;; - *-*-linux-gnu*) + *-*-freebsd* | *-*-linux* | *-*-dragonfly* | *-*-netbsd* | *-*-openbsd*) cat >>confdefs.h <<\_ACEOF #define LINUX 1 @@ -12185,7 +12583,7 @@ fi -ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc_net/Makefile include/Makefile docs/Makefile" +ac_config_files="$ac_config_files Makefile src/Makefile src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile src/cpu/core_dynrec/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile src/gui/Makefile src/hardware/Makefile src/hardware/serialport/Makefile src/ints/Makefile src/libs/Makefile src/libs/zmbv/Makefile src/misc/Makefile src/shell/Makefile src/platform/Makefile src/platform/visualc/Makefile visualc_net/Makefile include/Makefile docs/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -12598,7 +12996,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by dosbox $as_me 0.70, which was +This file was extended by dosbox $as_me 0.71, which was generated by GNU Autoconf 2.60a. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -12651,7 +13049,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -dosbox config.status 0.70 +dosbox config.status 0.71 configured by $0, generated by GNU Autoconf 2.60a, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -12772,6 +13170,7 @@ do "src/cpu/core_full/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_full/Makefile" ;; "src/cpu/core_normal/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_normal/Makefile" ;; "src/cpu/core_dyn_x86/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dyn_x86/Makefile" ;; + "src/cpu/core_dynrec/Makefile") CONFIG_FILES="$CONFIG_FILES src/cpu/core_dynrec/Makefile" ;; "src/debug/Makefile") CONFIG_FILES="$CONFIG_FILES src/debug/Makefile" ;; "src/dos/Makefile") CONFIG_FILES="$CONFIG_FILES src/dos/Makefile" ;; "src/fpu/Makefile") CONFIG_FILES="$CONFIG_FILES src/fpu/Makefile" ;; diff --git a/configure.in b/configure.in index c2fd357..c77bb4b 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Init. -AC_INIT(dosbox,0.70) +AC_INIT(dosbox,0.71) AC_PREREQ(2.50) AC_CONFIG_SRCDIR(README) @@ -20,7 +20,7 @@ AC_PROG_INSTALL AC_PROG_RANLIB dnl Some needed libaries for OS2 -dnl perharps join this with the other host depended checks. move them upwards +dnl perharps join this with the other target depended checks. move them upwards if test x$target = xi386-pc-os2-emx ; then CXXFLAGS="$CXXFLAGS -Zmt" LDFLAGS="$LDFLAGS -Zomf -Zmt" @@ -50,6 +50,42 @@ AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long long) AC_CHECK_SIZEOF(int *) +dnl some semi complex check for sys/socket so it works on darwin as well +AC_CHECK_HEADERS([stdlib.h sys/types.h]) +AC_CHECK_HEADERS([sys/socket.h netinet/in.h pwd.h], [], [], +[#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +]) + +dnl check for the socklen_t (darwin doesn't always have it) +AC_COMPILE_IFELSE([ +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +],[],[AC_DEFINE([socklen_t],[int],[Define to `int` if you don't have socklen_t])]) + AC_MSG_CHECKING(if environ can be included) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include @@ -93,7 +129,18 @@ int x=10;if( __builtin_expect ((x==1),0) ) ; #switch language back AC_LANG_POP(C++) -AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : ) +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)]), +[ case "${enableval}" in + yes) alsa_midi=true;; + no) alsa_midi=false;; +esac], +[alsa_midi=true]) +if test x$alsa_midi = xtrue ; then + AM_PATH_ALSA(0.9.0, AC_DEFINE(HAVE_ALSA,1,[Define to 1 to use ALSA for MIDI]) , : ) + CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS" +fi #Check for big endian machine, should #define WORDS_BIGENDIAN if so AC_C_BIGENDIAN @@ -135,41 +182,49 @@ AC_ARG_ENABLE(core-inline,AC_HELP_STRING([--enable-core-inline],[Enable inlined dnl The target cpu checks for dynamic cores -AH_TEMPLATE(C_HOSTCPU,[The type of cpu this host has]) +AH_TEMPLATE(C_TARGETCPU,[The type of cpu this target has]) AC_MSG_CHECKING(for target cpu type) case "$target_cpu" in + x86_64 | amd64) + AC_DEFINE(C_TARGETCPU,X86_64) + AC_MSG_RESULT(x86-64 bit compatible) + c_targetcpu="x86_64" + c_unalignedmemory=yes + ;; i?86) - AC_DEFINE(C_HOSTCPU,X86) + AC_DEFINE(C_TARGETCPU,X86) AC_MSG_RESULT(x86 compatible) - c_hostcpu="x86" + c_targetcpu="x86" c_unalignedmemory=yes ;; powerpc*) - AC_DEFINE(C_HOSTCPU,POWERPC) + AC_DEFINE(C_TARGETCPU,POWERPC) AC_MSG_RESULT(Power PC) - c_hostcpu="powerpc" + c_targetcpu="powerpc" c_unalignedmemory=yes ;; m68k*) - AC_DEFINE(C_HOSTCPU,M68K) + AC_DEFINE(C_TARGETCPU,M68K) AC_MSG_RESULT(Motorola 68000) - c_hostcpu="m68k" + c_targetcpu="m68k" c_unalignedmemory=yes ;; *) - AC_DEFINE(C_HOSTCPU,UNKOWN) + AC_DEFINE(C_TARGETCPU,UNKNOWN) AC_MSG_RESULT(unknown) c_unalignedmemory=no ;; 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) AC_MSG_CHECKING(whether x86 dynamic cpu core will be enabled) -if test x$enable_dynamic_x86 = xno ; then +if test x$enable_dynamic_x86 = xno -o x$enable_dynamic_core = xno; then AC_MSG_RESULT(no) else - if test x$c_hostcpu = xx86 ; then + if test x$c_targetcpu = xx86 ; then AC_DEFINE(C_DYNAMIC_X86,1) AC_MSG_RESULT(yes) else @@ -177,6 +232,30 @@ else fi fi +AH_TEMPLATE(C_DYNREC,[Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core]) +AC_ARG_ENABLE(dynrec,AC_HELP_STRING([--disable-dynrec],[Disable recompiling cpu core]),,enable_dynrec=yes) +AC_MSG_CHECKING(whether recompiling cpu core will be enabled) +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$enable_dynamic_x86 = xno ; then + AC_DEFINE(C_DYNREC,1) + AC_MSG_RESULT(yes) + else + 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 + AC_MSG_RESULT(no) + fi + fi +fi + AH_TEMPLATE(C_FPU,[Define to 1 to enable floating point emulation]) AC_ARG_ENABLE(fpu,AC_HELP_STRING([--disable-fpu],[Disable fpu support]),,enable_fpu=yes) AC_MSG_CHECKING(whether fpu emulation will be enabled) @@ -194,7 +273,7 @@ if test x$enable_fpu_x86 = xno ; then AC_MSG_RESULT(no) else if test x$enable_fpu = xyes; then - if test x$c_hostcpu = xx86 ; then + if test x$c_targetcpu = xx86 ; then AC_DEFINE(C_FPU_X86,1) AC_MSG_RESULT(yes) else @@ -249,6 +328,9 @@ else fi AH_TEMPLATE(C_OPENGL,[Define to 1 to use opengl display output support]) +AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , ) +AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , ) +AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , ) AC_ARG_ENABLE(opengl,AC_HELP_STRING([--disable-opengl],[Disable opengl support]),,enable_opengl=yes) AC_MSG_CHECKING(whether opengl display output will be enabled) if test x$enable_opengl = xyes; then @@ -259,9 +341,6 @@ case "$target" in AC_DEFINE(C_OPENGL,1) ;; *) - AC_CHECK_LIB(GL, main, have_gl_lib=yes, have_gl_lib=no , ) - AC_CHECK_LIB(opengl32, main, have_opengl32_lib=yes,have_opengl32_lib=no , ) - AC_CHECK_HEADER(GL/gl.h, have_gl_h=yes , have_gl_h=no , ) if test x$have_gl_h = xyes -a x$have_gl_lib = xyes ; then AC_MSG_RESULT(yes) LIBS="$LIBS -lGL" @@ -309,7 +388,7 @@ int main(int argc,char * argv[]) { ],AC_MSG_RESULT(yes);AC_DEFINE(C_SET_PRIORITY,1),AC_MSG_RESULT(no)) -dnl Some host detection and actions for them +dnl Some target detection and actions for them case "$target" in *-*-cygwin* | *-*-mingw32*) LIBS="$LIBS -lwinmm" @@ -327,8 +406,8 @@ case "$target" in AC_DEFINE(MACOSX, 1, [Compiling on Mac OS X]) LIBS="$LIBS -framework AudioUnit" ;; - *-*-linux-gnu*) - AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux]) + *-*-freebsd* | *-*-linux* | *-*-dragonfly* | *-*-netbsd* | *-*-openbsd*) + AC_DEFINE(LINUX, 1, [Compiling on GNU/Linux or *BSD]) AC_DEFINE(C_DIRECTSERIAL, 1, [ Define to 1 if you want serial passthrough support (Win32, Posix and OS/2).]) ;; *-*-os2-emx*) @@ -358,6 +437,7 @@ src/cpu/Makefile src/cpu/core_full/Makefile src/cpu/core_normal/Makefile src/cpu/core_dyn_x86/Makefile +src/cpu/core_dynrec/Makefile src/debug/Makefile src/dos/Makefile src/fpu/Makefile diff --git a/docs/Makefile.am b/docs/Makefile.am index 7e31317..682aab2 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,7 +1,7 @@ # Main Makefile for DOSBox man_MANS = dosbox.1 -EXTRA_DIST = $(man_MANS) README.video +EXTRA_DIST = $(man_MANS) README.video PORTING diff --git a/docs/Makefile.in b/docs/Makefile.in index 23deb41..b8caf0b 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -142,7 +142,7 @@ target_os = @target_os@ target_vendor = @target_vendor@ man_MANS = dosbox.1 -EXTRA_DIST = $(man_MANS) README.video +EXTRA_DIST = $(man_MANS) README.video PORTING subdir = docs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs diff --git a/docs/PORTING b/docs/PORTING new file mode 100644 index 0000000..b2d0b8a --- /dev/null +++ b/docs/PORTING @@ -0,0 +1,48 @@ +Some notes about porting DOSBox to systems with certain restrictions, +like handheld devices. + +If memory is a constraint: + - in paging.h reduce the size of the TLB: + #define TLB_SIZE (64*1024) + the 64 gives access to the first 256mb of linear memory + drawback: some protected mode games won't work then + gain: reduces memory requirements about ~15mb + TODO: limit vmemory access to the size of the TLB, + otherwise games which use >256mb vaddresses will crash badly + - in render.h lower the scaler integration: + #define RENDER_USE_ADVANCED_SCALERS 1 + or + #define RENDER_USE_ADVANCED_SCALERS 0 + drawback: complex scalers and the scaler cache are disabled, + be sure to test if this affects speed! + with define RENDER_USE_ADVANCED_SCALERS==0 most simple + scalers are disabled as well, some graphics modes won't + work due to reduced cache sizes + gain: ~2mb with RENDER_USE_ADVANCED_SCALERS==1 + ~5mb with RENDER_USE_ADVANCED_SCALERS==0 + - in dos_system.h reduce the drive cache entries: + #define MAX_OPENDIRS 256 + drawback: some apps might not work whith large directory trees + gain: ~1mb per mounted drive + - remove the GUS emulation (gus.cpp, especially GUSRam[1024*1024] ) + drawback: no gravis ultrasound + gain: reduces memory requirements about 1mb + - in vga.h reduce the size of the emulated graphics memory: + #define VGA_MEMORY (1*1024*1024) + drawback: some graphics modes won't work then + [EDIT: many modes won't work due to pixel caches] + gain: reduces memory requirements about 1mb + TODO: get this to actually work; + remove the respective svga modes, adapt some svga registers + +If speed is a constraint: + - see if the simple core is faster, possibly remove the normal core + set the simple core as default + drawback: one game is known to not work with the simple core; + the simple core does only work for games which don't use paging + (when paging is requested the normal core is used automatically) + gain: the simple core should be somewhat faster + TODO: add possibility to easily remove the normal core, use fullcore fallback + - raise the default frameskip value + drawback: minor graphics smoothness loss for some games (video playback) + gain: reduces graphics load diff --git a/docs/dosbox.1 b/docs/dosbox.1 index 8751a59..cefa701 100644 --- a/docs/dosbox.1 +++ b/docs/dosbox.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH DOSBOX 1 "Mar 28, 2006" +.TH DOSBOX 1 "Jul 01, 2007" .\" Please adjust this date whenever revising the manpage. .SH NAME dosbox \- an x86/DOS emulator with sound/graphics @@ -8,6 +8,8 @@ dosbox \- an x86/DOS emulator with sound/graphics .B [\-fullscreen] .B [\-startmapper] .B [\-noautoexec] +.BI "[\-scaler " scaler ] +.BI "[\-forcescaler " scaler ] .BI "[\-conf " configfile ] .BI "[\-lang " langfile ] .B [file] @@ -39,6 +41,14 @@ A summary of options is included below. .B \-noautoexec Skips the [autoexec] section of the loaded configuration file. .TP +.BI \-scaler " scaler" +.RI "Uses the graphical scaler specified by " scaler ". See the configuration" +file for the available scalers +.TP +.BI \-forcescaler " scaler" +.RB "Similar to the " \-scaler " parameter, but tries to force usage of" +the specified scaler even if it might not fit. +.TP .BI \-c " command" .RI "Runs the specified " command " before running " .BR file . @@ -74,7 +84,7 @@ following extra commands are available: .HP .BI "MOUNT [\-t " type "] [\-size " size ] .I driveletter sourcedirectory -.B [\-aspi] [\-ioctl] +.B [\-ioctl] .BI "[\-usecd " number "] [\-label " drivelabel "] [\-freesize " freesize ] .LP .B MOUNT \-cd @@ -115,18 +125,13 @@ If you do specify a label this label will be kept as long as the drive is mounted. It will not be updated !! .RE .TP -.B \-aspi -Forces to use the aspi layer. Only valid if mounting a cdrom under -Windows systems with an ASPI-Layer. -.TP .B \-ioctl -Forces to use ioctl commands. Only valid if mounting a cdrom under -windows which support them (Win2000/XP/NT). +Forces to use ioctl commands. .TP .BI \-usecd " number" Forces to use SDL cdrom support for drive number. .IR Number " can be found by " -.BR \-cd ". Valid on all systems." +.BR \-cd ". .TP .B \-cd .RB "Displays all detected cdrom drives and their numbers. Use with " \-usecd "." @@ -211,6 +216,13 @@ Boot will start floppy images or hard disk images independent of the .TP .RB "Read the " README " of " dosbox " for the full and correct syntax." .RE +.TP +.B KEYB +.LP +Keyb can change the keyboardlayout and the codepage used inside dosbox. +.TP +.RB "Read the " README " of " dosbox " for the full and correct syntax." +.RE .SH FILES Configuration and language files use a format similar to Windows .ini files. First ~/.dosboxrc (if present) will be loaded. If no diff --git a/include/callback.h b/include/callback.h index ccea2b1..aef5800 100644 --- a/include/callback.h +++ b/include/callback.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: callback.h,v 1.19 2007/01/08 19:45:37 qbix79 Exp $ */ +/* $Id: callback.h,v 1.21 2007/06/12 20:22:07 c2woody Exp $ */ #ifndef DOSBOX_CALLBACK_H #define DOSBOX_CALLBACK_H @@ -28,8 +28,8 @@ typedef Bitu (*CallBack_Handler)(void); extern CallBack_Handler CallBack_Handlers[]; -enum { CB_RETN,CB_RETF,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, +enum { CB_RETN,CB_RETF,CB_RETF8,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 }; #define CB_MAX 128 @@ -43,10 +43,10 @@ enum { extern Bit8u lastint; INLINE RealPt CALLBACK_RealPointer(Bitu callback) { - return RealMake(CB_SEG,callback*CB_SIZE); + return RealMake(CB_SEG,(Bit16u)(callback*CB_SIZE)); } INLINE PhysPt CALLBACK_PhysPointer(Bitu callback) { - return PhysMake(CB_SEG,callback*CB_SIZE); + return PhysMake(CB_SEG,(Bit16u)(callback*CB_SIZE)); } INLINE PhysPt CALLBACK_GetBase(void) { diff --git a/include/cpu.h b/include/cpu.h index 16e0d4c..fd86834 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -58,6 +58,8 @@ Bits CPU_Core_Simple_Run(void); Bits CPU_Core_Full_Run(void); Bits CPU_Core_Dyn_X86_Run(void); Bits CPU_Core_Dyn_X86_Trap_Run(void); +Bits CPU_Core_Dynrec_Run(void); +Bits CPU_Core_Dynrec_Trap_Run(void); //CPU Stuff @@ -68,10 +70,12 @@ bool CPU_LTR(Bitu selector); void CPU_LIDT(Bitu limit,Bitu base); void CPU_LGDT(Bitu limit,Bitu base); -void CPU_STR(Bitu & selector); -void CPU_SLDT(Bitu & selector); -void CPU_SIDT(Bitu & limit,Bitu & base); -void CPU_SGDT(Bitu & limit,Bitu & base); +Bitu CPU_STR(void); +Bitu CPU_SLDT(void); +Bitu CPU_SIDT_base(void); +Bitu CPU_SIDT_limit(void); +Bitu CPU_SGDT_base(void); +Bitu CPU_SGDT_limit(void); void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); void CPU_LAR(Bitu selector,Bitu & ar); @@ -88,8 +92,8 @@ bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue); bool CPU_WRITE_TRX(Bitu dr,Bitu value); bool CPU_READ_TRX(Bitu dr,Bit32u & retvalue); -void CPU_SMSW(Bitu & word); -Bitu CPU_LMSW(Bitu word); +Bitu CPU_SMSW(void); +bool CPU_LMSW(Bitu word); void CPU_VERR(Bitu selector); void CPU_VERW(Bitu selector); diff --git a/include/dos_inc.h b/include/dos_inc.h index 8c6e179..4b939f9 100644 --- a/include/dos_inc.h +++ b/include/dos_inc.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_inc.h,v 1.65 2007/01/08 20:36:53 qbix79 Exp $ */ +/* $Id: dos_inc.h,v 1.70 2007/07/20 18:53:52 qbix79 Exp $ */ #ifndef DOSBOX_DOS_INC_H #define DOSBOX_DOS_INC_H @@ -85,6 +85,9 @@ enum { RETURN_EXIT=0,RETURN_CTRLC=1,RETURN_ABORT=2,RETURN_TSR=3}; #define DOS_SDA_OFS 0 #define DOS_MEM_START 0x102 //First Segment that DOS can use +#define DOS_PRIVATE_SEGMENT 0xc800 +#define DOS_PRIVATE_SEGMENT_END 0xd000 + /* internal Dos Tables */ extern DOS_File * Files[DOS_FILES]; @@ -112,35 +115,35 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry); bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate); /* Routines for Drive Class */ -bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry); -bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status); -bool DOS_CreateFile(char * name,Bit16u attribute,Bit16u * entry); -bool DOS_UnlinkFile(char * name); +bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry); +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_UnlinkFile(char const * const name); bool DOS_FindFirst(char *search,Bit16u attr,bool fcb_findfirst=false); bool DOS_FindNext(void); -bool DOS_Canonicalize(char * name,char * big); -bool DOS_CreateTempFile(char * name,Bit16u * entry); -bool DOS_FileExists(char * name); +bool DOS_Canonicalize(char const * const name,char * const big); +bool DOS_CreateTempFile(char * const name,Bit16u * entry); +bool DOS_FileExists(char const * const name); /* Helper Functions */ -bool DOS_MakeName(char * name,char * fullname,Bit8u * drive); +bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive); /* Drive Handing Routines */ Bit8u DOS_GetDefaultDrive(void); void DOS_SetDefaultDrive(Bit8u drive); bool DOS_SetDrive(Bit8u drive); -bool DOS_GetCurrentDir(Bit8u drive,char * bugger); -bool DOS_ChangeDir(char * dir); -bool DOS_MakeDir(char * dir); -bool DOS_RemoveDir(char * dir); -bool DOS_Rename(char * oldname,char * newname); +bool DOS_GetCurrentDir(Bit8u drive,char * const buffer); +bool DOS_ChangeDir(char const * const dir); +bool DOS_MakeDir(char const * const dir); +bool DOS_RemoveDir(char const * const dir); +bool DOS_Rename(char const * const oldname,char const * const newname); bool DOS_GetFreeDiskSpace(Bit8u drive,Bit16u * bytes,Bit8u * sectors,Bit16u * clusters,Bit16u * free); -bool DOS_GetFileAttr(char * name,Bit16u * attr); -bool DOS_SetFileAttr(char * name,Bit16u attr); +bool DOS_GetFileAttr(char const * const name,Bit16u * attr); +bool DOS_SetFileAttr(char const * const name,Bit16u attr); /* IOCTL Stuff */ bool DOS_IOCTL(void); bool DOS_GetSTDINStatus(); -Bit8u DOS_FindDevice(char * name); +Bit8u DOS_FindDevice(char const * name); void DOS_SetupDevices(void); /* Execute and new process creation */ @@ -171,7 +174,7 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset, Bit16u numBlocks); Bit8u DOS_FCBWrite(Bit16u seg,Bit16u offset,Bit16u numBlocks); Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore); Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore); -bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec); +bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset); bool DOS_FCBDeleteFile(Bit16u seg,Bit16u offset); bool DOS_FCBRenameFile(Bit16u seg, Bit16u offset); void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset); @@ -257,9 +260,9 @@ public: } INLINE void SaveIt(Bitu size,PhysPt addr,Bitu val) { switch (size) { - case 1:mem_writeb(pt+addr,val);break; - case 2:mem_writew(pt+addr,val);break; - case 4:mem_writed(pt+addr,val);break; + case 1:mem_writeb(pt+addr,(Bit8u)val);break; + case 2:mem_writew(pt+addr,(Bit16u)val);break; + case 4:mem_writed(pt+addr,(Bit32u)val);break; } } INLINE void SetPt(Bit16u seg) { pt=PhysMake(seg,0);} @@ -280,14 +283,14 @@ public: void SaveVectors (void); void RestoreVectors (void); void SetSize (Bit16u size) { sSave(sPSP,next_seg,size); }; - Bit16u GetSize (void) { return sGet(sPSP,next_seg); }; + Bit16u GetSize (void) { return (Bit16u)sGet(sPSP,next_seg); }; void SetEnvironment (Bit16u envseg) { sSave(sPSP,environment,envseg); }; - Bit16u GetEnvironment (void) { return sGet(sPSP,environment); }; + Bit16u GetEnvironment (void) { return (Bit16u)sGet(sPSP,environment); }; Bit16u GetSegment (void) { return seg; }; void SetFileHandle (Bit16u index, Bit8u handle); Bit8u GetFileHandle (Bit16u index); void SetParent (Bit16u parent) { sSave(sPSP,psp_parent,parent); }; - Bit16u GetParent (void) { return sGet(sPSP,psp_parent); }; + Bit16u GetParent (void) { return (Bit16u)sGet(sPSP,psp_parent); }; void SetStack (RealPt stackpt) { sSave(sPSP,stack,stackpt); }; RealPt GetStack (void) { return sGet(sPSP,stack); }; void SetInt22 (RealPt int22pt) { sSave(sPSP,int_22,int22pt); }; @@ -455,8 +458,8 @@ public: void SetDirID(Bit16u entry) { sSave(sDTA,dirID,entry); }; void SetDirIDCluster(Bit16u entry) { sSave(sDTA,dirCluster,entry); }; - Bit16u GetDirID(void) { return sGet(sDTA,dirID); }; - Bit16u GetDirIDCluster(void) { return sGet(sDTA,dirCluster); }; + Bit16u GetDirID(void) { return (Bit16u)sGet(sDTA,dirID); }; + Bit16u GetDirIDCluster(void) { return (Bit16u)sGet(sDTA,dirCluster); }; private: #ifdef _MSC_VER #pragma pack(1) @@ -532,14 +535,14 @@ private: class DOS_MCB : public MemStruct{ public: DOS_MCB(Bit16u seg) { SetPt(seg); } - void SetFileName(char * _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); } - void GetFileName(char * _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;} + void SetFileName(char const * const _name) { MEM_BlockWrite(pt+offsetof(sMCB,filename),_name,8); } + void GetFileName(char * const _name) { MEM_BlockRead(pt+offsetof(sMCB,filename),_name,8);_name[8]=0;} void SetType(Bit8u _type) { sSave(sMCB,type,_type);} void SetSize(Bit16u _size) { sSave(sMCB,size,_size);} void SetPSPSeg(Bit16u _pspseg) { sSave(sMCB,psp_segment,_pspseg);} - Bit8u GetType(void) { return sGet(sMCB,type);} - Bit16u GetSize(void) { return sGet(sMCB,size);} - Bit16u GetPSPSeg(void) { return sGet(sMCB,psp_segment);} + Bit8u GetType(void) { return (Bit8u)sGet(sMCB,type);} + Bit16u GetSize(void) { return (Bit16u)sGet(sMCB,size);} + Bit16u GetPSPSeg(void) { return (Bit16u)sGet(sMCB,psp_segment);} private: #ifdef _MSC_VER #pragma pack (1) @@ -563,9 +566,9 @@ public: void SetDrive(Bit8u _drive) { sSave(sSDA,current_drive, _drive); } void SetDTA(Bit32u _dta) { sSave(sSDA,current_dta, _dta); } void SetPSP(Bit16u _psp) { sSave(sSDA,current_psp, _psp); } - Bit8u GetDrive(void) { return sGet(sSDA,current_drive); } - Bit16u GetPSP(void) { return sGet(sSDA,current_psp); } - Bit32u GetDTA(void) { return sGet(sSDA,current_dta); } + Bit8u GetDrive(void) { return (Bit8u)sGet(sSDA,current_drive); } + Bit16u GetPSP(void) { return (Bit16u)sGet(sSDA,current_psp); } + Bit32u GetDTA(void) { return (Bit32u)sGet(sSDA,current_dta); } private: @@ -620,6 +623,7 @@ struct DOS_Block { RealPt filenamechar; RealPt collatingseq; Bit8u* country;//Will be copied to dos memory. resides in real mem + Bit16u dpb; //Fake Disk parameter system using only the first entry so the drive letter matches } tables; Bit16u loaded_codepage; }; diff --git a/include/dos_system.h b/include/dos_system.h index f695e10..131d681 100644 --- a/include/dos_system.h +++ b/include/dos_system.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_system.h,v 1.39 2007/01/21 16:21:22 c2woody Exp $ */ +/* $Id: dos_system.h,v 1.40 2007/06/13 07:25:14 qbix79 Exp $ */ #ifndef DOSBOX_DOS_SYSTEM_H #define DOSBOX_DOS_SYSTEM_H @@ -80,12 +80,10 @@ public: virtual bool UpdateDateTimeFromHost() { return true; } void SetDrive(Bit8u drv) { hdrive=drv;} Bit8u GetDrive(void) { return hdrive;} - Bit8u type; Bit32u flags; Bit16u time; Bit16u date; Bit16u attr; - Bit32u size; Bits refCtr; bool open; char* name; diff --git a/include/fpu.h b/include/fpu.h index 50511ea..2c07180 100644 --- a/include/fpu.h +++ b/include/fpu.h @@ -114,8 +114,8 @@ INLINE void FPU_SetTag(Bit16u tag){ } INLINE void FPU_SetCW(Bitu word){ - fpu.cw = word; - fpu.cw_mask_all = word | 0x3f; + fpu.cw = (Bit16u)word; + fpu.cw_mask_all = (Bit16u)(word | 0x3f); fpu.round = (FPU_Round)((word >> 10) & 3); } diff --git a/include/inout.h b/include/inout.h index 6a60012..bc18abe 100644 --- a/include/inout.h +++ b/include/inout.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: inout.h,v 1.10 2007/01/08 19:45:37 qbix79 Exp $ */ +/* $Id: inout.h,v 1.11 2007/06/12 20:22:07 c2woody Exp $ */ #ifndef DOSBOX_INOUT_H #define DOSBOX_INOUT_H @@ -72,7 +72,7 @@ INLINE void IO_Write(Bitu port,Bit8u val) { IO_WriteB(port,val); } INLINE Bit8u IO_Read(Bitu port){ - return IO_ReadB(port); + return (Bit8u)IO_ReadB(port); } #endif diff --git a/include/mem.h b/include/mem.h index 9c3a5df..436dc38 100644 --- a/include/mem.h +++ b/include/mem.h @@ -150,7 +150,7 @@ INLINE Bit32u phys_readd(PhysPt addr){ /* These don't check for alignment, better be sure it's correct */ -void MEM_BlockWrite(PhysPt pt,void * data,Bitu size); +void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size); void MEM_BlockRead(PhysPt pt,void * data,Bitu size); void MEM_BlockCopy(PhysPt dest,PhysPt src,Bitu size); void MEM_StrCopy(PhysPt pt,char * data,Bitu size); diff --git a/include/paging.h b/include/paging.h index f9c70e8..1ac785b 100644 --- a/include/paging.h +++ b/include/paging.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: paging.h,v 1.24 2007/01/08 19:45:37 qbix79 Exp $ */ +/* $Id: paging.h,v 1.25 2007/06/12 20:22:07 c2woody Exp $ */ #ifndef DOSBOX_PAGING_H #define DOSBOX_PAGING_H @@ -179,7 +179,7 @@ bool mem_unalignedwrited_checked_x86(PhysPt address,Bit32u val); INLINE Bit8u mem_readb_inline(PhysPt address) { Bitu index=(address>>12); if (paging.tlb.read[index]) return host_readb(paging.tlb.read[index]+address); - else return paging.tlb.handler[index]->readb(address); + else return (Bit8u)paging.tlb.handler[index]->readb(address); } INLINE Bit16u mem_readw_inline(PhysPt address) { @@ -187,7 +187,7 @@ INLINE Bit16u mem_readw_inline(PhysPt address) { Bitu index=(address>>12); if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address); - else return paging.tlb.handler[index]->readw(address); + else return (Bit16u) paging.tlb.handler[index]->readw(address); } else return mem_unalignedreadw(address); } @@ -231,7 +231,7 @@ INLINE Bit16u mem_readw_dyncorex86(PhysPt address) { Bitu index=(address>>12); if (paging.tlb.read[index]) return host_readw(paging.tlb.read[index]+address); - else return paging.tlb.handler[index]->readw(address); + else return (Bit16u)paging.tlb.handler[index]->readw(address); } else return mem_unalignedreadw(address); } diff --git a/include/pic.h b/include/pic.h index 4d37ded..420a1fe 100644 --- a/include/pic.h +++ b/include/pic.h @@ -49,7 +49,7 @@ INLINE Bits PIC_MakeCycles(double amount) { } INLINE double PIC_FullIndex(void) { - return PIC_Ticks+PIC_TickIndex(); + return PIC_Ticks+(double)PIC_TickIndex(); } void PIC_ActivateIRQ(Bitu irq); diff --git a/include/regs.h b/include/regs.h index 636b676..0f5a0c4 100644 --- a/include/regs.h +++ b/include/regs.h @@ -98,7 +98,7 @@ INLINE PhysPt SegPhys(SegNames index) { } INLINE Bit16u SegValue(SegNames index) { - return Segs.val[index]; + return (Bit16u)Segs.val[index]; } INLINE RealPt RealMakeSeg(SegNames index,Bit16u off) { diff --git a/include/render.h b/include/render.h index 93d20f2..6e85971 100644 --- a/include/render.h +++ b/include/render.h @@ -19,6 +19,12 @@ #ifndef DOSBOX_RENDER_H #define DOSBOX_RENDER_H +// 0: complex scalers off, scaler cache off, some simple scalers off, memory requirements reduced +// 1: complex scalers off, scaler cache off, all simple scalers on +// 2: complex scalers off, scaler cache on +// 3: complex scalers on +#define RENDER_USE_ADVANCED_SCALERS 3 + #include "../src/gui/render_scalers.h" #define RENDER_SKIP_CACHE 16 @@ -63,6 +69,7 @@ typedef struct { scalerMode_t outMode; scalerOperation_t op; bool clearCache; + bool forced; ScalerLineHandler_t lineHandler; ScalerLineHandler_t linePalHandler; ScalerComplexHandler_t complexHandler; diff --git a/include/setup.h b/include/setup.h index 02ebe1f..55db8c4 100644 --- a/include/setup.h +++ b/include/setup.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: setup.h,v 1.26 2007/01/08 19:45:37 qbix79 Exp $ */ +/* $Id: setup.h,v 1.27 2007/06/14 08:23:46 qbix79 Exp $ */ #ifndef DOSBOX_SETUP_H #define DOSBOX_SETUP_H @@ -142,8 +142,8 @@ private: public: Section(char const * const _sectionname):sectionname(_sectionname) { } - void AddInitFunction(SectionFunction func,bool canchange=false) {initfunctions.push_back(Function_wrapper(func,canchange));} - void AddDestroyFunction(SectionFunction func,bool canchange=false) {destroyfunctions.push_front(Function_wrapper(func,canchange));} + void AddInitFunction(SectionFunction func,bool canchange=false); + void AddDestroyFunction(SectionFunction func,bool canchange=false); void ExecuteInit(bool initall=true); void ExecuteDestroy(bool destroyall=true); const char* GetName() const {return sectionname.c_str();} diff --git a/include/shell.h b/include/shell.h index ca95043..b4dec7c 100644 --- a/include/shell.h +++ b/include/shell.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.h,v 1.20 2007/01/08 19:59:06 qbix79 Exp $ */ +/* $Id: shell.h,v 1.21 2007/06/14 08:23:46 qbix79 Exp $ */ #ifndef DOSBOX_SHELL_H #define DOSBOX_SHELL_H @@ -77,7 +77,7 @@ public: void DoCommand(char * cmd); bool Execute(char * name,char * args); /* Checks if it matches a hardware-property */ - bool CheckConfig(char* cmd,char*line); + bool CheckConfig(char* cmd_in,char*line); /* Some internal used functions */ char * Which(char * name); /* Some supported commands */ diff --git a/src/Makefile.am b/src/Makefile.am index bccc59a..870a0db 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,13 +4,15 @@ SUBDIRS = cpu debug dos fpu gui hardware libs ints misc shell platform bin_PROGRAMS = dosbox +if HAVE_WINDRES +ico_stuff = dosbox_ico.o +endif + + dosbox_SOURCES = dosbox.cpp 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 - -if HAVE_WINDRES -dosbox_LDADD += dosbox_ico.o -endif + ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a \ + $(ico_stuff) EXTRA_DIST = dosbox.rc dosbox.ico dosbox_ico.o: dosbox.rc dosbox.ico diff --git a/src/Makefile.in b/src/Makefile.in index a3ba64b..b0e61da 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -36,7 +36,6 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : host_triplet = @host@ -@HAVE_WINDRES_TRUE@am__append_1 = dosbox_ico.o ACLOCAL = @ACLOCAL@ ALSA_CFLAGS = @ALSA_CFLAGS@ ALSA_LIBS = @ALSA_LIBS@ @@ -145,10 +144,13 @@ SUBDIRS = cpu debug dos fpu gui hardware libs ints misc shell platform bin_PROGRAMS = dosbox +@HAVE_WINDRES_TRUE@ico_stuff = dosbox_ico.o + dosbox_SOURCES = dosbox.cpp 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\ -$(am__append_1) + ints/libints.a misc/libmisc.a shell/libshell.a hardware/serialport/libserial.a \ + $(ico_stuff) + EXTRA_DIST = dosbox.rc dosbox.ico subdir = src diff --git a/src/cpu/Makefile.am b/src/cpu/Makefile.am index 62cc988..0d6c542 100644 --- a/src/cpu/Makefile.am +++ b/src/cpu/Makefile.am @@ -1,7 +1,7 @@ -SUBDIRS = core_full core_normal core_dyn_x86 +SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \ - core_dyn_x86.cpp \ No newline at end of file + core_dyn_x86.cpp core_dynrec.cpp diff --git a/src/cpu/Makefile.in b/src/cpu/Makefile.in index 6382a29..6a76438 100644 --- a/src/cpu/Makefile.in +++ b/src/cpu/Makefile.in @@ -138,13 +138,13 @@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ -SUBDIRS = core_full core_normal core_dyn_x86 +SUBDIRS = core_full core_normal core_dyn_x86 core_dynrec AM_CPPFLAGS = -I$(top_srcdir)/include noinst_LIBRARIES = libcpu.a libcpu_a_SOURCES = callback.cpp cpu.cpp flags.cpp modrm.cpp modrm.h core_full.cpp instructions.h \ paging.cpp lazyflags.h core_normal.cpp core_simple.cpp \ - core_dyn_x86.cpp + core_dyn_x86.cpp core_dynrec.cpp subdir = src/cpu ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -158,7 +158,7 @@ libcpu_a_LIBADD = am_libcpu_a_OBJECTS = callback.$(OBJEXT) cpu.$(OBJEXT) flags.$(OBJEXT) \ modrm.$(OBJEXT) core_full.$(OBJEXT) paging.$(OBJEXT) \ core_normal.$(OBJEXT) core_simple.$(OBJEXT) \ - core_dyn_x86.$(OBJEXT) + core_dyn_x86.$(OBJEXT) core_dynrec.$(OBJEXT) libcpu_a_OBJECTS = $(am_libcpu_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) @@ -166,7 +166,8 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/callback.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_dyn_x86.Po \ -@AMDEP_TRUE@ ./$(DEPDIR)/core_full.Po ./$(DEPDIR)/core_normal.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/core_dynrec.Po ./$(DEPDIR)/core_full.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/core_normal.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/core_simple.Po ./$(DEPDIR)/cpu.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/flags.Po ./$(DEPDIR)/modrm.Po \ @AMDEP_TRUE@ ./$(DEPDIR)/paging.Po @@ -217,6 +218,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callback.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dyn_x86.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_dynrec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_full.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_normal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/core_simple.Po@am__quote@ diff --git a/src/cpu/callback.cpp b/src/cpu/callback.cpp index b92b478..40e1bc6 100644 --- a/src/cpu/callback.cpp +++ b/src/cpu/callback.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: callback.cpp,v 1.36 2007/01/08 19:45:38 qbix79 Exp $ */ +/* $Id: callback.cpp,v 1.37 2007/06/03 16:46:33 c2woody Exp $ */ #include #include @@ -155,6 +155,16 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_ } phys_writeb(physAddress+0x00,(Bit8u)0xCB); //A RETF Instruction return (use_cb?5:1); + case CB_RETF8: + if (use_cb) { + phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 + phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction + phys_writew(physAddress+0x02, callback); //The immediate word + physAddress+=4; + } + phys_writeb(physAddress+0x00,(Bit8u)0xCA); //A RETF 8 Instruction + phys_writew(physAddress+0x01,(Bit16u)0x0008); + return (use_cb?7:3); case CB_IRET: if (use_cb) { phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 @@ -300,6 +310,18 @@ Bitu CALLBACK_SetupExtra(Bitu callback, Bitu type, PhysPt physAddress, bool use_ phys_writeb(physAddress+0x0e,(Bit8u)0x58); // pop ax phys_writeb(physAddress+0x0f,(Bit8u)0xcf); //An IRET Instruction return (use_cb?0x14:0x10); + case CB_MOUSE: + phys_writew(physAddress+0x00,(Bit16u)0x07eb); // jmp i33hd + physAddress+=9; + // jump here to (i33hd): + if (use_cb) { + phys_writeb(physAddress+0x00,(Bit8u)0xFE); //GRP 4 + phys_writeb(physAddress+0x01,(Bit8u)0x38); //Extra Callback instruction + phys_writew(physAddress+0x02,callback); //The immediate word + physAddress+=4; + } + phys_writeb(physAddress+0x00,(Bit8u)0xCF); //An IRET Instruction + return (use_cb?0x0e:0x0a); case CB_INT16: phys_writeb(physAddress+0x00,(Bit8u)0xFB); //STI if (use_cb) { diff --git a/src/cpu/core_dyn_x86.cpp b/src/cpu/core_dyn_x86.cpp index fc34251..8e78b8a 100644 --- a/src/cpu/core_dyn_x86.cpp +++ b/src/cpu/core_dyn_x86.cpp @@ -27,6 +27,11 @@ #include #include +#if defined (WIN32) +#include +#include +#endif + #if (C_HAVE_MPROTECT) #include @@ -45,7 +50,7 @@ #include "inout.h" #include "fpu.h" -#define CACHE_MAXSIZE (4096*2) +#define CACHE_MAXSIZE (4096*3) #define CACHE_TOTAL (1024*1024*8) #define CACHE_PAGES (512) #define CACHE_BLOCKS (64*1024) @@ -258,12 +263,11 @@ Bits CPU_Core_Dyn_X86_Run(void) { /* Determine the linear address of CS:EIP */ restart_core: PhysPt ip_point=SegPhys(cs)+reg_eip; - Bitu ip_page=ip_point>>12; #if C_HEAVY_DEBUG if (DEBUG_HeavyIsBreakpoint()) return debugCallback; #endif CodePageHandler * chandler=0; - if (GCC_UNLIKELY(MakeCodePage(ip_page,chandler))) { + if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { CPU_Exception(cpu.exception.which,cpu.exception.error); goto restart_core; } diff --git a/src/cpu/core_dyn_x86/cache.h b/src/cpu/core_dyn_x86/cache.h index 7fe2965..968f26c 100644 --- a/src/cpu/core_dyn_x86/cache.h +++ b/src/cpu/core_dyn_x86/cache.h @@ -66,7 +66,7 @@ public: } } bool InvalidateRange(Bitu start,Bitu end) { - Bits index=1+(start>>DYN_HASH_SHIFT); + Bits index=1+(end>>DYN_HASH_SHIFT); bool is_current_block=false; Bit32u ip_point=SegPhys(cs)+reg_eip; ip_point=((paging.tlb.phys_page[ip_point>>12]-phys_page)<<12)+(ip_point&0xfff); @@ -457,8 +457,15 @@ static void cache_init(bool enable) { } } 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); - if(!cache_code_start_ptr) E_Exit("Allocating dynamic cache failed"); +#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. @@ -510,6 +517,8 @@ static void cache_close(void) { cache_blocks = NULL; } if (cache_code_start_ptr != NULL) { + ### care: under windows VirtualFree() has to be used if + ### VirtualAlloc was used for memory allocation free(cache_code_start_ptr); cache_code_start_ptr = NULL; } diff --git a/src/cpu/core_dyn_x86/decoder.h b/src/cpu/core_dyn_x86/decoder.h index 9bdf851..d9456f4 100644 --- a/src/cpu/core_dyn_x86/decoder.h +++ b/src/cpu/core_dyn_x86/decoder.h @@ -50,10 +50,11 @@ static struct DynDecode { DynReg * segprefix; } decode; -static bool MakeCodePage(Bitu lin_page,CodePageHandler * &cph) { +static bool MakeCodePage(Bitu lin_addr,CodePageHandler * &cph) { Bit8u rdval; //Ensure page contains memory: - if (GCC_UNLIKELY(mem_readb_checked_x86(lin_page << 12,&rdval))) return true; + if (GCC_UNLIKELY(mem_readb_checked_x86(lin_addr,&rdval))) return true; + Bitu lin_page=lin_addr >> 12; PageHandler * handler=paging.tlb.handler[lin_page]; if (handler->flags & PFLAG_HASCODE) { cph=( CodePageHandler *)handler; @@ -99,8 +100,10 @@ static Bit8u decode_fetchb(void) { /* Advance to the next page */ decode.active_block->page.end=4095; /* trigger possible page fault here */ - mem_readb((++decode.page.first) << 12); - MakeCodePage(decode.page.first,decode.page.code); + decode.page.first++; + Bitu fetchaddr=decode.page.first << 12; + mem_readb(fetchaddr); + MakeCodePage(fetchaddr,decode.page.code); CacheBlock * newblock=cache_getblock(); decode.active_block->crossblock=newblock; newblock->crossblock=decode.active_block; @@ -142,7 +145,7 @@ static Bit32u decode_fetchd(void) { #define START_WMMEM 64 -static void INLINE decode_increase_wmapmask(Bitu size) { +static INLINE void decode_increase_wmapmask(Bitu size) { Bitu mapidx; CacheBlock* activecb=decode.active_block; if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { @@ -252,7 +255,8 @@ static INLINE void dyn_set_eip_end(void) { static INLINE void dyn_set_eip_end(DynReg * endreg) { gen_protectflags(); - gen_dop_word(DOP_MOV,cpu.code.big,DREG(TMPW),DREG(EIP)); + if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(TMPW),DREG(EIP)); + else gen_extend_word(false,DREG(TMPW),DREG(EIP)); gen_dop_word_imm(DOP_ADD,cpu.code.big,DREG(TMPW),decode.code-decode.code_start); } @@ -923,7 +927,7 @@ static void dyn_pop(DynReg * dynreg,bool checked=true) { } } -static void INLINE dyn_get_modrm(void) { +static INLINE void 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; @@ -1183,7 +1187,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); + dyn_write_byte_release(DREG(EA),rm_reg,rm_regi==4); } else { gen_dop_byte(DOP_MOV,&DynRegs[decode.modrm.rm&3],decode.modrm.rm&4,rm_reg,rm_regi); } @@ -1810,7 +1814,8 @@ static void dyn_call_near_imm(void) { dyn_set_eip_end(DREG(TMPW)); dyn_push(DREG(TMPW)); gen_dop_word_imm(DOP_ADD,decode.big_op,DREG(TMPW),imm); - gen_dop_word(DOP_MOV,decode.big_op,DREG(EIP),DREG(TMPW)); + if (cpu.code.big) gen_dop_word(DOP_MOV,true,DREG(EIP),DREG(TMPW)); + else gen_extend_word(false,DREG(EIP),DREG(TMPW)); dyn_reduce_cycles(); dyn_save_critical_regs(); gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlock,cache.start)); @@ -2182,14 +2187,14 @@ restart_prefix: gen_releasereg(DREG(ESP)); dyn_flags_gen_to_host(); gen_call_function((void *)&CPU_PUSHF,"%Rd%Id",DREG(TMPB),decode.big_op); - if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB)); + dyn_check_bool_exception(DREG(TMPB)); gen_releasereg(DREG(TMPB)); break; case 0x9d: //POPF gen_releasereg(DREG(ESP)); gen_releasereg(DREG(FLAGS)); gen_call_function((void *)&CPU_POPF,"%Rd%Id",DREG(TMPB),decode.big_op); - if (cpu.pmode) dyn_check_bool_exception(DREG(TMPB)); + dyn_check_bool_exception(DREG(TMPB)); dyn_flags_host_to_gen(); gen_releasereg(DREG(TMPB)); break; @@ -2556,7 +2561,7 @@ restart_prefix: dyn_save_critical_regs(); gen_call_function( decode.modrm.reg == 3 ? (void*)&CPU_CALL : (void*)&CPU_JMP, - decode.big_op ? (char *)"%Id%Drw%Drd%Drd" : (char *)"%Id%Drw%Drw%Drd", + decode.big_op ? "%Id%Drw%Drd%Drd" : "%Id%Drw%Drw%Drd", decode.big_op,DREG(EA),DREG(TMPW),DREG(TMPB)); dyn_flags_host_to_gen(); goto core_close_block; @@ -2589,7 +2594,6 @@ illegalopcode: dyn_closeblock(); goto finish_block; #if (C_DEBUG) -illegalopcodefull: dyn_set_eip_last(); dyn_reduce_cycles(); dyn_save_critical_regs(); diff --git a/src/cpu/core_dyn_x86/dyn_fpu.h b/src/cpu/core_dyn_x86/dyn_fpu.h index e47fc67..6bd25b4 100644 --- a/src/cpu/core_dyn_x86/dyn_fpu.h +++ b/src/cpu/core_dyn_x86/dyn_fpu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2005 The DOSBox Team + * Copyright (C) 2002-2007 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 @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dyn_fpu.h,v 1.2 2006/09/19 16:27:58 c2woody Exp $ */ +/* $Id: dyn_fpu.h,v 1.3 2007/06/14 17:47:24 c2woody Exp $ */ #include "dosbox.h" #if C_FPU diff --git a/src/cpu/core_dyn_x86/dyn_fpu_dh.h b/src/cpu/core_dyn_x86/dyn_fpu_dh.h index e485a2b..7a6c3ce 100644 --- a/src/cpu/core_dyn_x86/dyn_fpu_dh.h +++ b/src/cpu/core_dyn_x86/dyn_fpu_dh.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002-2005 The DOSBox Team + * Copyright (C) 2002-2007 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 @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dyn_fpu_dh.h,v 1.2 2006/11/11 14:42:38 c2woody Exp $ */ +/* $Id: dyn_fpu_dh.h,v 1.4 2007/06/14 17:47:24 c2woody Exp $ */ #include "dosbox.h" #if C_FPU @@ -65,7 +65,7 @@ static void FPU_FLDCW_DH(PhysPt addr){ } static void FPU_FNSTCW_DH(PhysPt addr){ - mem_writew(addr,dyn_dh_fpu.cw); + mem_writew(addr,(Bit16u)(dyn_dh_fpu.cw&0xffff)); } static void FPU_FNINIT_DH(void){ diff --git a/src/cpu/core_dyn_x86/risc_x86.h b/src/cpu/core_dyn_x86/risc_x86.h index d5f15bf..08ea139 100644 --- a/src/cpu/core_dyn_x86/risc_x86.h +++ b/src/cpu/core_dyn_x86/risc_x86.h @@ -163,7 +163,7 @@ static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) { genreg->Load(dynreg,stale); return genreg; } - if (genreg->last_usedlast_used<(Bitu)first_used) { first_used=genreg->last_used; first_index=i; } @@ -176,7 +176,7 @@ static GenReg * FindDynReg(DynReg * dynreg,bool stale=false) { genreg->Load(dynreg,stale); return genreg; } - if (genreg->last_usedlast_used<(Bitu)first_used) { first_used=genreg->last_used; first_index=i; } @@ -721,11 +721,11 @@ static void gen_dshift_cl(bool dword,bool left,DynReg * dr1,DynReg * dr2,DynReg dr1->flags|=DYNFLG_CHANGED; } -static void gen_call_function(void * func,char * ops,...) { +static void gen_call_function(void * func,char const* ops,...) { Bits paramcount=0; bool release_flags=false; struct ParamInfo { - char * line; + const char * line; Bitu value; } pinfo[32]; ParamInfo * retparam=0; @@ -743,10 +743,10 @@ static void gen_call_function(void * func,char * ops,...) { Bits pindex=0; while (*ops) { if (*ops=='%') { - pinfo[pindex].line=ops+1; + pinfo[pindex].line=ops+1; pinfo[pindex].value=va_arg(params,Bitu); #if defined (MACOSX) - char * scan=pinfo[pindex].line; + const char * scan=pinfo[pindex].line; if ((*scan=='I') || (*scan=='D')) stack_used+=4; else if (*scan=='F') free_flags=true; #endif @@ -777,7 +777,7 @@ static void gen_call_function(void * func,char * ops,...) { paramcount=0; while (pindex) { pindex--; - char * scan=pinfo[pindex].line; + const char * scan=pinfo[pindex].line; switch (*scan++) { case 'I': /* immediate value */ paramcount++; diff --git a/src/cpu/core_dynrec.cpp b/src/cpu/core_dynrec.cpp new file mode 100644 index 0000000..f9af3ef --- /dev/null +++ b/src/cpu/core_dynrec.cpp @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2002-2007 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. + */ + +#include "dosbox.h" + +#if (C_DYNREC) + +#include +#include +#include +#include +#include +#include + +#if defined (WIN32) +#include +#include +#endif + +#if (C_HAVE_MPROTECT) +#include + +#include +#ifndef PAGESIZE +#define PAGESIZE 4096 +#endif +#endif /* C_HAVE_MPROTECT */ + +#include "callback.h" +#include "regs.h" +#include "mem.h" +#include "cpu.h" +#include "debug.h" +#include "paging.h" +#include "inout.h" +#include "lazyflags.h" + +#define CACHE_MAXSIZE (4096) +#define CACHE_TOTAL (1024*1024*8) +#define CACHE_PAGES (512) +#define CACHE_BLOCKS (128*1024) +#define CACHE_ALIGN (16) +#define DYN_HASH_SHIFT (4) +#define DYN_PAGE_HASH (4096>>DYN_HASH_SHIFT) +#define DYN_LINKS (16) + +#if 0 +#define DYN_LOG LOG_MSG +#else +#define DYN_LOG +#endif + +#if C_FPU +#define CPU_FPU 1 //Enable FPU escape instructions +#endif + + +// the emulated x86 registers +#define DRC_REG_EAX 0 +#define DRC_REG_ECX 1 +#define DRC_REG_EDX 2 +#define DRC_REG_EBX 3 +#define DRC_REG_ESP 4 +#define DRC_REG_EBP 5 +#define DRC_REG_ESI 6 +#define DRC_REG_EDI 7 + +// the emulated x86 segment registers +#define DRC_SEG_ES 0 +#define DRC_SEG_CS 1 +#define DRC_SEG_SS 2 +#define DRC_SEG_DS 3 +#define DRC_SEG_FS 4 +#define DRC_SEG_GS 5 + + +// access to a general register +#define DRCD_REG(reg) (&cpu_regs.regs[reg].dword) +// access to a segment register +#define DRCD_SEG_VAL(seg) (&Segs.val[seg]) +// access to the physical value of a segment register/selector +#define DRCD_SEG_PHYS(seg) (&Segs.phys[seg]) + +// access to an 8bit general register +#define DRCD_REG_BYTE(reg,idx) (&cpu_regs.regs[reg].byte[idx]) +// access to 16/32bit general registers +#define DRCD_REG_WORD(reg,dwrd) ((dwrd)?((void*)(&cpu_regs.regs[reg].dword)):((void*)(&cpu_regs.regs[reg].word))) + + +enum BlockReturn { + BR_Normal=0, + BR_Cycles, + BR_Link1,BR_Link2, + BR_Opcode, +#if (C_DEBUG) + BR_OpcodeFull, +#endif + BR_Iret, + BR_CallBack, + BR_SMCBlock +}; + +// identificator to signal self-modification of the currently executed block +#define SMC_CURRENT_BLOCK 0xffff + + +static void IllegalOptionDynrec(const char* msg) { + E_Exit("DynrecCore: illegal option in %s",msg); +} + +static struct { + BlockReturn (*runcode)(Bit8u*); // points to code that can start a block + Bitu callback; // the occurred callback + Bitu readdata; // spare space used when reading from memory + Bit32u protected_regs[8]; // space to save/restore register values +} core_dynrec; + + +#include "core_dynrec/cache.h" + +#define X86 0x01 +#define X86_64 0x02 +#define MIPSEL32 0x03 + +#if C_TARGETCPU == X86_64 +#include "core_dynrec/risc_x64.h" +#elif C_TARGETCPU == X86 +#include "core_dynrec/risc_x86.h" +#elif C_TARGETCPU == MIPSEL32 +#include "core_dynrec/risc_mipsel32.h" +#endif + +#include "core_dynrec/decoder.h" + +CacheBlockDynRec * LinkBlocks(BlockReturn ret) { + CacheBlockDynRec * block=NULL; + // the last instruction was a control flow modifying instruction + Bitu temp_ip=SegPhys(cs)+reg_eip; + Bitu temp_page=temp_ip >> 12; + CodePageHandlerDynRec * temp_handler=(CodePageHandlerDynRec *)paging.tlb.handler[temp_page]; + if (temp_handler->flags & PFLAG_HASCODE) { + // 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; + } + return NULL; +} + +/* + The core tries to find the block that should be executed next. + If such a block is found, it is run, otherwise the instruction + stream starting at ip_point is translated (see decoder.h) and + makes up a new code block that will be run. + When control is returned to CPU_Core_Dynrec_Run (which might + be right after the block is run, or somewhen long after that + due to the direct cacheblock linking) the returncode decides + the next action. This might be continuing the translation and + execution process, or returning from the core etc. +*/ + +Bits CPU_Core_Dynrec_Run(void) { + for (;;) { + // Determine the linear address of CS:EIP + PhysPt ip_point=SegPhys(cs)+reg_eip; + #if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; + #endif + + CodePageHandlerDynRec * chandler=0; + // see if the current page is present and contains code + if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) { + // page not present, throw the exception + CPU_Exception(cpu.exception.which,cpu.exception.error); + continue; + } + + // page doesn't contain code or is special + if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run(); + + // find correct Dynamic Block to run + CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095); + if (!block) { + // no block found, thus translate the instruction stream + // unless the instruction is known to be modified + if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) { + // translate up to 32 instructions + block=CreateCacheBlock(chandler,ip_point,32); + } else { + // let the normal core handle this instruction to avoid zero-sized blocks + Bitu old_cycles=CPU_Cycles; + CPU_Cycles=1; + Bits nc_retcode=CPU_Core_Normal_Run(); + if (!nc_retcode) { + CPU_Cycles=old_cycles-1; + continue; + } + CPU_CycleLeft+=old_cycles; + return nc_retcode; + } + } + +run_block: + cache.block.running=0; + // now we're ready to run the dynamic code block +// BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))(); + BlockReturn ret=core_dynrec.runcode(block->cache.start); + + switch (ret) { + case BR_Iret: +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; +#endif + if (!GETFLAG(TF)) break; + // trapflag is set, switch to the trap-aware decoder + cpudecoder=CPU_Core_Dynrec_Trap_Run; + return CBRET_NONE; + + case BR_Normal: + // the block was exited due to a non-predictable control flow + // modifying instruction (like ret) or some nontrivial cpu state + // changing instruction (for example switch to/from pmode), + // or the maximal number of instructions to translate was reached +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; +#endif + break; + + case BR_Cycles: + // cycles went negative, return from the core to handle + // external events, schedule the pic... +#if C_HEAVY_DEBUG + if (DEBUG_HeavyIsBreakpoint()) return debugCallback; +#endif + return CBRET_NONE; + + case BR_CallBack: + // the callback code is executed in dosbox.conf, return the callback number + FillFlags(); + return core_dynrec.callback; + + case BR_SMCBlock: +// LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip); + cpu.exception.which=0; + // fallthrough, let the normal core handle the block-modifying instruction + case BR_Opcode: + // some instruction has been encountered that could not be translated + // (thus it is not part of the code block), the normal core will + // handle this instruction + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=1; + return CPU_Core_Normal_Run(); + +#if (C_DEBUG) + case BR_OpcodeFull: + CPU_CycleLeft+=CPU_Cycles; + CPU_Cycles=1; + return CPU_Core_Full_Run(); +#endif + + case BR_Link1: + case BR_Link2: + block=LinkBlocks(ret); + if (block) goto run_block; + break; + + default: + E_Exit("Invalid return code %d", ret); + } + } + return CBRET_NONE; +} + +Bits CPU_Core_Dynrec_Trap_Run(void) { + Bits oldCycles = CPU_Cycles; + CPU_Cycles = 1; + cpu.trap_skip = false; + + // let the normal core execute the next (only one!) instruction + Bits ret=CPU_Core_Normal_Run(); + + // trap to int1 unless the last instruction deferred this + // (allows hardware interrupts to be served without interaction) + if (!cpu.trap_skip) CPU_HW_Interrupt(1); + + CPU_Cycles = oldCycles-1; + // continue (either the trapflag was clear anyways, or the int1 cleared it) + cpudecoder = &CPU_Core_Dynrec_Run; + + return ret; +} + +void CPU_Core_Dynrec_Init(void) { +} + +void CPU_Core_Dynrec_Cache_Init(bool enable_cache) { + // Initialize code cache and dynamic blocks + cache_init(enable_cache); +} + +void CPU_Core_Dynrec_Cache_Close(void) { + cache_close(); +} + +#endif diff --git a/src/cpu/core_dynrec/Makefile.am b/src/cpu/core_dynrec/Makefile.am new file mode 100644 index 0000000..50c57a7 --- /dev/null +++ b/src/cpu/core_dynrec/Makefile.am @@ -0,0 +1,2 @@ +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 \ No newline at end of file diff --git a/src/cpu/core_dynrec/Makefile.in b/src/cpu/core_dynrec/Makefile.in new file mode 100644 index 0000000..4dd40d9 --- /dev/null +++ b/src/cpu/core_dynrec/Makefile.in @@ -0,0 +1,332 @@ +# Makefile.in generated by automake 1.7.9 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../../.. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ +ACLOCAL = @ACLOCAL@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +GREP = @GREP@ +HAVE_WINDRES_FALSE = @HAVE_WINDRES_FALSE@ +HAVE_WINDRES_TRUE = @HAVE_WINDRES_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SDL_CFLAGS = @SDL_CFLAGS@ +SDL_CONFIG = @SDL_CONFIG@ +SDL_LIBS = @SDL_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +WINDRES = @WINDRES@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +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 + +subdir = src/cpu/core_dynrec +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/cpu/core_dynrec/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \ + distclean distclean-generic distclean-tags distdir dvi dvi-am \ + info info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/cpu/core_dynrec/cache.h b/src/cpu/core_dynrec/cache.h new file mode 100644 index 0000000..c8f1785 --- /dev/null +++ b/src/cpu/core_dynrec/cache.h @@ -0,0 +1,642 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +class CodePageHandlerDynRec; // forward + +// basic cache block representation +class CacheBlockDynRec { +public: + void Clear(void); + // link this cache block to another block, index specifies the code + // path (always zero for unconditional links, 0/1 for conditional ones + void LinkTo(Bitu index,CacheBlockDynRec * toblock) { + assert(toblock); + link[index].to=toblock; + link[index].next=toblock->link[index].from; // set target block + toblock->link[index].from=this; // remember who links me + } + struct { + Bit16u start,end; // where in the page is the original code + CodePageHandlerDynRec * handler; // page containing this code + } page; + struct { + Bit8u * start; // where in the cache are we + Bitu size; + CacheBlockDynRec * next; + // writemap masking maskpointer/start/length + // to allow holes in the writemap + Bit8u * wmapmask; + Bit16u maskstart; + Bit16u masklen; + } cache; + struct { + Bitu index; + CacheBlockDynRec * next; + } hash; + struct { + CacheBlockDynRec * to; // this block can transfer control to the to-block + CacheBlockDynRec * next; + CacheBlockDynRec * from; // the from-block can transfer control to this block + } link[2]; // maximal two links (conditional jumps) + CacheBlockDynRec * crossblock; +}; + +static struct { + struct { + CacheBlockDynRec * first; // the first cache block in the list + CacheBlockDynRec * active; // the current cache block + CacheBlockDynRec * free; // pointer to the free list + CacheBlockDynRec * running; // the last block that was entered for execution + } block; + Bit8u * pos; // position in the cache block + CodePageHandlerDynRec * free_pages; // pointer to the free list + CodePageHandlerDynRec * used_pages; // pointer to the list of used pages + CodePageHandlerDynRec * last_page; // the last used page +} cache; + +static CacheBlockDynRec link_blocks[2]; // default linking (specially marked) + +// the CodePageHandlerDynRec class provides access to the contained +// cache blocks and intercepts writes to the code for special treatment +class CodePageHandlerDynRec : public PageHandler { +public: + CodePageHandlerDynRec() { + invalidation_map=NULL; + } + + void SetupAt(Bitu _phys_page,PageHandler * _old_pagehandler) { + // initialize this codepage handler + phys_page=_phys_page; + // save the old pagehandler to provide direct read access to the memory, + // and to be able to restore it later on + old_pagehandler=_old_pagehandler; + + // adjust flags + flags=old_pagehandler->flags|PFLAG_HASCODE; + flags&=~PFLAG_WRITEABLE; + + active_blocks=0; + active_count=16; + + // initialize the maps with zero (no cache blocks as well as code present) + memset(&hash_map,0,sizeof(hash_map)); + memset(&write_map,0,sizeof(write_map)); + if (invalidation_map!=NULL) { + free(invalidation_map); + invalidation_map=NULL; + } + } + + // clear out blocks that contain code which has been modified + bool InvalidateRange(Bitu start,Bitu end) { + Bits index=1+(end>>DYN_HASH_SHIFT); + bool is_current_block=false; // if the current block is modified, it has to be exited as soon as possible + + Bit32u ip_point=SegPhys(cs)+reg_eip; + ip_point=((paging.tlb.phys_page[ip_point>>12]-phys_page)<<12)+(ip_point&0xfff); + while (index>=0) { + Bitu map=0; + // see if there is still some code in the range + for (Bitu count=start;count<=end;count++) map+=write_map[count]; + if (!map) return is_current_block; // no more code, finished + + CacheBlockDynRec * block=hash_map[index]; + while (block) { + CacheBlockDynRec * nextblock=block->hash.next; + // test if this block is in the range + if (start<=block->page.end && end>=block->page.start) { + if (ip_point<=block->page.end && ip_point>=block->page.start) is_current_block=true; + block->Clear(); // clear the block, decrements the write_map accordingly + } + block=nextblock; + } + index--; + } + return is_current_block; + } + + // the following functions will clean all cache blocks that are invalid now due to the write + void writeb(PhysPt addr,Bitu val){ + addr&=4095; + if (host_readb(hostmem+addr)==(Bit8u)val) return; + host_writeb(hostmem+addr,val); + // see if there's code where we are writing to + if (!*(Bit8u*)&write_map[addr]) { + if (active_blocks) return; // still some blocks in this page + active_count--; + if (!active_count) Release(); // delay page releasing until active_count is zero + return; + } else if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + invalidation_map[addr]++; + InvalidateRange(addr,addr); + } + void writew(PhysPt addr,Bitu val){ + addr&=4095; + if (host_readw(hostmem+addr)==(Bit16u)val) return; + host_writew(hostmem+addr,val); + // see if there's code where we are writing to + if (!*(Bit16u*)&write_map[addr]) { + if (active_blocks) return; // still some blocks in this page + active_count--; + if (!active_count) Release(); // delay page releasing until active_count is zero + return; + } else if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + (*(Bit16u*)&invalidation_map[addr])+=0x101; + InvalidateRange(addr,addr+1); + } + void writed(PhysPt addr,Bitu val){ + addr&=4095; + if (host_readd(hostmem+addr)==(Bit32u)val) return; + host_writed(hostmem+addr,val); + // see if there's code where we are writing to + if (!*(Bit32u*)&write_map[addr]) { + if (active_blocks) return; // still some blocks in this page + active_count--; + if (!active_count) Release(); // delay page releasing until active_count is zero + return; + } else if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + (*(Bit32u*)&invalidation_map[addr])+=0x1010101; + InvalidateRange(addr,addr+3); + } + bool writeb_checked(PhysPt addr,Bitu val) { + addr&=4095; + if (host_readb(hostmem+addr)==(Bit8u)val) return false; + // see if there's code where we are writing to + if (!*(Bit8u*)&write_map[addr]) { + if (!active_blocks) { + // no blocks left in this page, still delay the page releasing a bit + active_count--; + if (!active_count) Release(); + } + } else { + if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + invalidation_map[addr]++; + if (InvalidateRange(addr,addr)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + } + host_writeb(hostmem+addr,val); + return false; + } + bool writew_checked(PhysPt addr,Bitu val) { + addr&=4095; + if (host_readw(hostmem+addr)==(Bit16u)val) return false; + // see if there's code where we are writing to + if (!*(Bit16u*)&write_map[addr]) { + if (!active_blocks) { + // no blocks left in this page, still delay the page releasing a bit + active_count--; + if (!active_count) Release(); + } + } else { + if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + (*(Bit16u*)&invalidation_map[addr])+=0x101; + if (InvalidateRange(addr,addr+1)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + } + host_writew(hostmem+addr,val); + return false; + } + bool writed_checked(PhysPt addr,Bitu val) { + addr&=4095; + if (host_readd(hostmem+addr)==(Bit32u)val) return false; + // see if there's code where we are writing to + if (!*(Bit32u*)&write_map[addr]) { + if (!active_blocks) { + // no blocks left in this page, still delay the page releasing a bit + active_count--; + if (!active_count) Release(); + } + } else { + if (!invalidation_map) { + invalidation_map=(Bit8u*)malloc(4096); + memset(invalidation_map,0,4096); + } + (*(Bit32u*)&invalidation_map[addr])+=0x1010101; + if (InvalidateRange(addr,addr+3)) { + cpu.exception.which=SMC_CURRENT_BLOCK; + return true; + } + } + host_writed(hostmem+addr,val); + return false; + } + + // add a cache block to this page and note it in the hash map + void AddCacheBlock(CacheBlockDynRec * block) { + Bitu index=1+(block->page.start>>DYN_HASH_SHIFT); + block->hash.next=hash_map[index]; // link to old block at index from the new block + block->hash.index=index; + hash_map[index]=block; // put new block at hash position + block->page.handler=this; + active_blocks++; + } + // there's a block whose code started in a different page + void AddCrossBlock(CacheBlockDynRec * block) { + block->hash.next=hash_map[0]; + block->hash.index=0; + hash_map[0]=block; + block->page.handler=this; + active_blocks++; + } + // remove a cache block + void DelCacheBlock(CacheBlockDynRec * block) { + active_blocks--; + active_count=16; + CacheBlockDynRec * * bwhere=&hash_map[block->hash.index]; + while (*bwhere!=block) { + bwhere=&((*bwhere)->hash.next); + //Will crash if a block isn't found, which should never happen. + } + *bwhere=block->hash.next; + + // remove the cleared block from the write map + if (GCC_UNLIKELY(block->cache.wmapmask!=NULL)) { + // first part is not influenced by the mask + for (Bitu i=block->page.start;icache.maskstart;i++) { + if (write_map[i]) write_map[i]--; + } + Bitu maskct=0; + // last part sticks to the writemap mask + for (Bitu i=block->cache.maskstart;i<=block->page.end;i++,maskct++) { + if (write_map[i]) { + // only adjust writemap if it isn't masked + if ((maskct>=block->cache.masklen) || (!block->cache.wmapmask[maskct])) write_map[i]--; + } + } + free(block->cache.wmapmask); + block->cache.wmapmask=NULL; + } else { + for (Bitu i=block->page.start;i<=block->page.end;i++) { + if (write_map[i]) write_map[i]--; + } + } + } + + void Release(void) { + MEM_SetPageHandler(phys_page,1,old_pagehandler); // revert to old handler + PAGING_ClearTLB(); + + // remove page from the lists + if (prev) prev->next=next; + else cache.used_pages=next; + if (next) next->prev=prev; + else cache.last_page=prev; + next=cache.free_pages; + cache.free_pages=this; + prev=0; + } + void ClearRelease(void) { + // clear out all cache blocks in this page + for (Bitu index=0;index<(1+DYN_PAGE_HASH);index++) { + CacheBlockDynRec * block=hash_map[index]; + while (block) { + CacheBlockDynRec * nextblock=block->hash.next; + block->page.handler=0; // no need, full clear + block->Clear(); + block=nextblock; + } + } + Release(); // now can release this page + } + + CacheBlockDynRec * FindCacheBlock(Bitu start) { + CacheBlockDynRec * block=hash_map[1+(start>>DYN_HASH_SHIFT)]; + // see if there's a cache block present at the start address + while (block) { + if (block->page.start==start) return block; // found + block=block->hash.next; + } + return 0; // none found + } + + HostPt GetHostReadPt(Bitu phys_page) { + hostmem=old_pagehandler->GetHostReadPt(phys_page); + return hostmem; + } + HostPt GetHostWritePt(Bitu phys_page) { + return GetHostReadPt( phys_page ); + } +public: + // the write map, there are write_map[i] cache blocks that cover the byte at address i + Bit8u write_map[4096]; + Bit8u * invalidation_map; + CodePageHandlerDynRec * next, * prev; // page linking +private: + PageHandler * old_pagehandler; + + // hash map to quickly find the cache blocks in this page + CacheBlockDynRec * hash_map[1+DYN_PAGE_HASH]; + + Bitu active_blocks; // the number of cache blocks in this page + Bitu active_count; // delaying parameter to not immediately release a page + HostPt hostmem; + Bitu phys_page; +}; + + +static INLINE void cache_addunusedblock(CacheBlockDynRec * block) { + // block has become unused, add it to the freelist + block->cache.next=cache.block.free; + cache.block.free=block; +} + +static CacheBlockDynRec * cache_getblock(void) { + // get a free cache block and advance the free pointer + CacheBlockDynRec * ret=cache.block.free; + if (!ret) E_Exit("Ran out of CacheBlocks" ); + cache.block.free=ret->cache.next; + ret->cache.next=0; + return ret; +} + +void CacheBlockDynRec::Clear(void) { + Bitu ind; + // check if this is not a cross page block + if (hash.index) for (ind=0;ind<2;ind++) { + CacheBlockDynRec * fromlink=link[ind].from; + link[ind].from=0; + while (fromlink) { + CacheBlockDynRec * nextlink=fromlink->link[ind].next; + // clear the next-link and let the block point to the standard linkcode + fromlink->link[ind].next=0; + fromlink->link[ind].to=&link_blocks[ind]; + + fromlink=nextlink; + } + if (link[ind].to!=&link_blocks[ind]) { + // not linked to the standard linkcode, find the block that links to this block + CacheBlockDynRec * * wherelink=&link[ind].to->link[ind].from; + while (*wherelink != this && *wherelink) { + wherelink = &(*wherelink)->link[ind].next; + } + // now remove the link + if(*wherelink) + *wherelink = (*wherelink)->link[ind].next; + else { + LOG(LOG_CPU,LOG_ERROR)("Cache anomaly. please investigate"); + } + } + } else + cache_addunusedblock(this); + if (crossblock) { + // clear out the crossblock (in the page before) as well + crossblock->crossblock=0; + crossblock->Clear(); + crossblock=0; + } + if (page.handler) { + // clear out the code page handler + page.handler->DelCacheBlock(this); + page.handler=0; + } + if (cache.wmapmask){ + free(cache.wmapmask); + cache.wmapmask=NULL; + } +} + + +static CacheBlockDynRec * cache_openblock(void) { + CacheBlockDynRec * block=cache.block.active; + // check for enough space in this block + Bitu size=block->cache.size; + CacheBlockDynRec * nextblock=block->cache.next; + if (block->page.handler) + block->Clear(); + // block size must be at least CACHE_MAXSIZE + while (sizecache.size; + CacheBlockDynRec * tempblock=nextblock->cache.next; + if (nextblock->page.handler) + nextblock->Clear(); + // block is free now + cache_addunusedblock(nextblock); + nextblock=tempblock; + } +skipresize: + // adjust parameters and open this block + block->cache.size=size; + block->cache.next=nextblock; + cache.pos=block->cache.start; + return block; +} + +static void cache_closeblock(void) { + CacheBlockDynRec * block=cache.block.active; + // links point to the default linking code + block->link[0].to=&link_blocks[0]; + block->link[1].to=&link_blocks[1]; + block->link[0].from=0; + block->link[1].from=0; + block->link[0].next=0; + block->link[1].next=0; + // close the block with correct alignment + Bitu written=(Bitu)(cache.pos-block->cache.start); + if (written>block->cache.size) { + if (!block->cache.next) { + if (written>block->cache.size+CACHE_MAXSIZE) E_Exit("CacheBlock overrun 1 %d",written-block->cache.size); + } else E_Exit("CacheBlock overrun 2 written %d size %d",written,block->cache.size); + } else { + Bitu new_size; + Bitu left=block->cache.size-written; + // smaller than cache align then don't bother to resize + if (left>CACHE_ALIGN) { + new_size=((written-1)|(CACHE_ALIGN-1))+1; + CacheBlockDynRec * newblock=cache_getblock(); + // align block now to CACHE_ALIGN + newblock->cache.start=block->cache.start+new_size; + newblock->cache.size=block->cache.size-new_size; + newblock->cache.next=block->cache.next; + block->cache.next=newblock; + block->cache.size=new_size; + } + } + // advance the active block pointer + if (!block->cache.next) { +// LOG_MSG("Cache full restarting"); + cache.block.active=cache.block.first; + } else { + cache.block.active=block->cache.next; + } +} + + +// place an 8bit value into the cache +static INLINE void cache_addb(Bit8u val) { + *cache.pos++=val; +} + +// place a 16bit value into the cache +static INLINE void cache_addw(Bit16u val) { + *(Bit16u*)cache.pos=val; + cache.pos+=2; +} + +// place a 32bit value into the cache +static INLINE void cache_addd(Bit32u val) { + *(Bit32u*)cache.pos=val; + cache.pos+=4; +} + +// place a 64bit value into the cache +static INLINE void cache_addq(Bit64u val) { + *(Bit64u*)cache.pos=val; + cache.pos+=8; +} + + +static void dyn_return(BlockReturn retcode,bool ret_exception); +static void dyn_run_code(void); + +// cache memory pointers, to be malloc'd later +static Bit8u * cache_code_start_ptr=NULL; +static Bit8u * cache_code=NULL; +static Bit8u * cache_code_link_blocks=NULL; +static CacheBlockDynRec * cache_blocks=NULL; + +/* Define temporary pagesize so the MPROTECT case and the regular case share as much code as possible */ +#if (C_HAVE_MPROTECT) +#define PAGESIZE_TEMP PAGESIZE +#else +#define PAGESIZE_TEMP 4096 +#endif + +static bool cache_initialized = false; + +static void cache_init(bool enable) { + Bits i; + if (enable) { + // see if cache is already initialized + if (cache_initialized) return; + cache_initialized = true; + if (cache_blocks == NULL) { + // allocate the cache blocks memory + cache_blocks=(CacheBlockDynRec*)malloc(CACHE_BLOCKS*sizeof(CacheBlockDynRec)); + if(!cache_blocks) E_Exit("Allocating cache_blocks has failed"); + memset(cache_blocks,0,sizeof(CacheBlockDynRec)*CACHE_BLOCKS); + cache.block.free=&cache_blocks[0]; + // initialize the cache blocks + for (i=0;icache.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; + // link code that returns with a special return code + dyn_return(BR_Link1,false); + cache.pos=&cache_code_link_blocks[32]; + link_blocks[1].cache.start=cache.pos; + // link code that returns with a special return code + dyn_return(BR_Link2,false); + + cache.pos=&cache_code_link_blocks[64]; + core_dynrec.runcode=(BlockReturn (*)(Bit8u*))cache.pos; +// link_blocks[1].cache.start=cache.pos; + dyn_run_code(); + + cache.free_pages=0; + cache.last_page=0; + cache.used_pages=0; + // setup the code pages + for (i=0;inext=cache.free_pages; + cache.free_pages=newpage; + } + } +} + +static void cache_close(void) { +/* 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) { + free(cache_blocks); + cache_blocks = NULL; + } + if (cache_code_start_ptr != NULL) { + ### care: under windows VirtualFree() has to be used if + ### VirtualAlloc was used for memory allocation + free(cache_code_start_ptr); + cache_code_start_ptr = NULL; + } + cache_code = NULL; + cache_code_link_blocks = NULL; + cache_initialized = false; */ +} diff --git a/src/cpu/core_dynrec/decoder.h b/src/cpu/core_dynrec/decoder.h new file mode 100644 index 0000000..13c47b4 --- /dev/null +++ b/src/cpu/core_dynrec/decoder.h @@ -0,0 +1,582 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +#include "decoder_basic.h" +#include "operators.h" +#include "decoder_opcodes.h" + +#include "dyn_fpu.h" + +/* + The function CreateCacheBlock translates the instruction stream + until either an unhandled instruction is found, the maximal + number of translated instructions is reached or some critical + instruction is encountered. +*/ + +static CacheBlockDynRec * CreateCacheBlock(CodePageHandlerDynRec * codepage,PhysPt start,Bitu max_opcodes) { + // initialize a load of variables + decode.code_start=start; + decode.code=start; + decode.page.code=codepage; + decode.page.index=start&4095; + decode.page.wmap=codepage->write_map; + decode.page.invmap=codepage->invalidation_map; + decode.page.first=start >> 12; + decode.active_block=decode.block=cache_openblock(); + decode.block->page.start=(Bit16u)decode.page.index; + codepage->AddCacheBlock(decode.block); + + InitFlagsOptimization(); + + // every codeblock that is run sets cache.block.running to itself + // so the block linking knows the last executed block + gen_mov_direct_ptr(&cache.block.running,(DRC_PTR_SIZE_IM)decode.block); + + // start with the cycles check + gen_mov_word_to_reg(FC_RETOP,&CPU_Cycles,true); + save_info_dynrec[used_save_info_dynrec].branch_pos=gen_create_branch_long_leqzero(FC_RETOP); + save_info_dynrec[used_save_info_dynrec].type=cycle_check; + used_save_info_dynrec++; + + decode.cycles=0; + while (max_opcodes--) { + // Init prefixes + decode.big_addr=cpu.code.big; + decode.big_op=cpu.code.big; + decode.seg_prefix=0; + decode.seg_prefix_used=false; + decode.rep=REP_NONE; + decode.cycles++; + decode.op_start=decode.code; +restart_prefix: + Bitu opcode; + if (!decode.page.invmap) opcode=decode_fetchb(); + else { + // some entries in the invalidation map, see if the next + // instruction is known to be modified a lot + if (decode.page.index<4096) { + if (GCC_UNLIKELY(decode.page.invmap[decode.page.index]>=4)) goto illegalopcode; + opcode=decode_fetchb(); + } else { + // switch to the next page + opcode=decode_fetchb(); + if (GCC_UNLIKELY(decode.page.invmap && + (decode.page.invmap[decode.page.index-1]>=4))) goto illegalopcode; + } + } + switch (opcode) { + // instructions 'op reg8,reg8' and 'op [],reg8' + case 0x00:dyn_dop_ebgb(DOP_ADD);break; + case 0x08:dyn_dop_ebgb(DOP_OR);break; + case 0x10:dyn_dop_ebgb(DOP_ADC);break; + case 0x18:dyn_dop_ebgb(DOP_SBB);break; + case 0x20:dyn_dop_ebgb(DOP_AND);break; + case 0x28:dyn_dop_ebgb(DOP_SUB);break; + case 0x30:dyn_dop_ebgb(DOP_XOR);break; + case 0x38:dyn_dop_ebgb(DOP_CMP);break; + + // instructions 'op reg8,reg8' and 'op reg8,[]' + case 0x02:dyn_dop_gbeb(DOP_ADD);break; + case 0x0a:dyn_dop_gbeb(DOP_OR);break; + case 0x12:dyn_dop_gbeb(DOP_ADC);break; + case 0x1a:dyn_dop_gbeb(DOP_SBB);break; + case 0x22:dyn_dop_gbeb(DOP_AND);break; + case 0x2a:dyn_dop_gbeb(DOP_SUB);break; + case 0x32:dyn_dop_gbeb(DOP_XOR);break; + case 0x3a:dyn_dop_gbeb(DOP_CMP);break; + + // instructions 'op reg16/32,reg16/32' and 'op [],reg16/32' + case 0x01:dyn_dop_evgv(DOP_ADD);break; + case 0x09:dyn_dop_evgv(DOP_OR);break; + case 0x11:dyn_dop_evgv(DOP_ADC);break; + case 0x19:dyn_dop_evgv(DOP_SBB);break; + case 0x21:dyn_dop_evgv(DOP_AND);break; + case 0x29:dyn_dop_evgv(DOP_SUB);break; + case 0x31:dyn_dop_evgv(DOP_XOR);break; + case 0x39:dyn_dop_evgv(DOP_CMP);break; + + // instructions 'op reg16/32,reg16/32' and 'op reg16/32,[]' + case 0x03:dyn_dop_gvev(DOP_ADD);break; + case 0x0b:dyn_dop_gvev(DOP_OR);break; + case 0x13:dyn_dop_gvev(DOP_ADC);break; + case 0x1b:dyn_dop_gvev(DOP_SBB);break; + case 0x23:dyn_dop_gvev(DOP_AND);break; + case 0x2b:dyn_dop_gvev(DOP_SUB);break; + case 0x33:dyn_dop_gvev(DOP_XOR);break; + case 0x3b:dyn_dop_gvev(DOP_CMP);break; + + // instructions 'op reg8,imm8' + case 0x04:dyn_dop_byte_imm(DOP_ADD,DRC_REG_EAX,0);break; + case 0x0c:dyn_dop_byte_imm(DOP_OR,DRC_REG_EAX,0);break; + case 0x14:dyn_dop_byte_imm(DOP_ADC,DRC_REG_EAX,0);break; + case 0x1c:dyn_dop_byte_imm(DOP_SBB,DRC_REG_EAX,0);break; + case 0x24:dyn_dop_byte_imm(DOP_AND,DRC_REG_EAX,0);break; + case 0x2c:dyn_dop_byte_imm(DOP_SUB,DRC_REG_EAX,0);break; + case 0x34:dyn_dop_byte_imm(DOP_XOR,DRC_REG_EAX,0);break; + case 0x3c:dyn_dop_byte_imm(DOP_CMP,DRC_REG_EAX,0);break; + + // instructions 'op reg16/32,imm16/32' + case 0x05:dyn_dop_word_imm(DOP_ADD,DRC_REG_EAX);break; + case 0x0d:dyn_dop_word_imm_old(DOP_OR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0x15:dyn_dop_word_imm_old(DOP_ADC,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0x1d:dyn_dop_word_imm_old(DOP_SBB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0x25:dyn_dop_word_imm(DOP_AND,DRC_REG_EAX);break; + case 0x2d:dyn_dop_word_imm_old(DOP_SUB,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0x35:dyn_dop_word_imm_old(DOP_XOR,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + case 0x3d:dyn_dop_word_imm_old(DOP_CMP,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + + // push segment register onto stack + case 0x06:dyn_push_seg(DRC_SEG_ES);break; + case 0x0e:dyn_push_seg(DRC_SEG_CS);break; + case 0x16:dyn_push_seg(DRC_SEG_SS);break; + case 0x1e:dyn_push_seg(DRC_SEG_DS);break; + + // pop segment register from stack + case 0x07:dyn_pop_seg(DRC_SEG_ES);break; + case 0x17:dyn_pop_seg(DRC_SEG_SS);break; + case 0x1f:dyn_pop_seg(DRC_SEG_DS);break; + + // segment prefixes + case 0x26:dyn_segprefix(DRC_SEG_ES);goto restart_prefix; + case 0x2e:dyn_segprefix(DRC_SEG_CS);goto restart_prefix; + case 0x36:dyn_segprefix(DRC_SEG_SS);goto restart_prefix; + case 0x3e:dyn_segprefix(DRC_SEG_DS);goto restart_prefix; + case 0x64:dyn_segprefix(DRC_SEG_FS);goto restart_prefix; + case 0x65:dyn_segprefix(DRC_SEG_GS);goto restart_prefix; + +// case 0x27: DAA missing +// case 0x2f: DAS missing +// case 0x37: AAA missing +// case 0x3f: AAS missing + + // dual opcodes + case 0x0f: + { + Bitu dual_code=decode_fetchb(); + switch (dual_code) { + case 0x00: + if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; + dyn_grp6(); + break; + case 0x01: + if (dyn_grp7()) goto finish_block; + break; +/* case 0x02: + if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; + dyn_larlsl(true); + break; + case 0x03: + if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; + dyn_larlsl(false); + break; */ + + case 0x20:dyn_mov_from_crx();break; + case 0x22:dyn_mov_to_crx();goto finish_block; + + // short conditional jumps + case 0x80:case 0x81:case 0x82:case 0x83:case 0x84:case 0x85:case 0x86:case 0x87: + case 0x88:case 0x89:case 0x8a:case 0x8b:case 0x8c:case 0x8d:case 0x8e:case 0x8f: + dyn_branched_exit((BranchTypes)(dual_code&0xf), + decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); + goto finish_block; + + // conditional byte set instructions +/* case 0x90:case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: + case 0x98:case 0x99:case 0x9a:case 0x9b:case 0x9c:case 0x9d:case 0x9e:case 0x9f: + dyn_set_byte_on_condition((BranchTypes)(dual_code&0xf)); + AcquireFlags(FMASK_TEST); + break; */ + + // push/pop segment registers + case 0xa0:dyn_push_seg(DRC_SEG_FS);break; + case 0xa1:dyn_pop_seg(DRC_SEG_FS);break; + case 0xa8:dyn_push_seg(DRC_SEG_GS);break; + case 0xa9:dyn_pop_seg(DRC_SEG_GS);break; + + // double shift instructions + case 0xa4:dyn_dshift_ev_gv(true,true);break; + case 0xa5:dyn_dshift_ev_gv(true,false);break; + case 0xac:dyn_dshift_ev_gv(false,true);break; + case 0xad:dyn_dshift_ev_gv(false,false);break; + + case 0xaf:dyn_imul_gvev(0);break; + + case 0xb4:dyn_load_seg_off_ea(DRC_SEG_FS);break; + case 0xb5:dyn_load_seg_off_ea(DRC_SEG_GS);break; + + // zero-extending moves + case 0xb6:dyn_movx_ev_gb(false);break; + case 0xb7:dyn_movx_ev_gw(false);break; + + // sign-extending moves + case 0xbe:dyn_movx_ev_gb(true);break; + case 0xbf:dyn_movx_ev_gw(true);break; + + default: +// DYN_LOG("Unhandled dual opcode 0F%02X",dual_code); + goto illegalopcode; + } + break; + } + + // 'inc/dec reg16/32' + case 0x40:case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46:case 0x47: + dyn_sop_word(SOP_INC,opcode&7); + break; + case 0x48:case 0x49:case 0x4a:case 0x4b:case 0x4c:case 0x4d:case 0x4e:case 0x4f: + dyn_sop_word(SOP_DEC,opcode&7); + break; + + // 'push/pop reg16/32' + case 0x50:case 0x51:case 0x52:case 0x53:case 0x54:case 0x55:case 0x56:case 0x57: + dyn_push_reg(opcode&7); + break; + case 0x58:case 0x59:case 0x5a:case 0x5b:case 0x5c:case 0x5d:case 0x5e:case 0x5f: + dyn_pop_reg(opcode&7); + break; + + case 0x60: + if (decode.big_op) gen_call_function_raw((void *)&dynrec_pusha_dword); + else gen_call_function_raw((void *)&dynrec_pusha_word); + break; + case 0x61: + if (decode.big_op) gen_call_function_raw((void *)&dynrec_popa_dword); + else gen_call_function_raw((void *)&dynrec_popa_word); + break; + +// case 0x62: BOUND missing +// case 0x61: ARPL missing + + case 0x66:decode.big_op=!cpu.code.big;goto restart_prefix; + case 0x67:decode.big_addr=!cpu.code.big;goto restart_prefix; + + // 'push imm8/16/32' + case 0x68: + dyn_push_word_imm(decode.big_op ? decode_fetchd() : decode_fetchw()); + break; + case 0x6a: + dyn_push_byte_imm((Bit8s)decode_fetchb()); + break; + + // signed multiplication + case 0x69:dyn_imul_gvev(decode.big_op ? 4 : 2);break; + case 0x6b:dyn_imul_gvev(1);break; + +// case 0x6c to 0x6f missing (ins/outs) + + // short conditional jumps + case 0x70:case 0x71:case 0x72:case 0x73:case 0x74:case 0x75:case 0x76:case 0x77: + case 0x78:case 0x79:case 0x7a:case 0x7b:case 0x7c:case 0x7d:case 0x7e:case 0x7f: + dyn_branched_exit((BranchTypes)(opcode&0xf),(Bit8s)decode_fetchb()); + goto finish_block; + + // 'op []/reg8,imm8' + case 0x80: + case 0x82:dyn_grp1_eb_ib();break; + + // 'op []/reg16/32,imm16/32' + case 0x81:dyn_grp1_ev_iv(false);break; + case 0x83:dyn_grp1_ev_iv(true);break; + + // 'test []/reg8/16/32,reg8/16/32' + case 0x84:dyn_dop_gbeb(DOP_TEST);break; + case 0x85:dyn_dop_gvev(DOP_TEST);break; + + // 'xchg reg8/16/32,[]/reg8/16/32' + case 0x86:dyn_dop_ebgb_xchg();break; + case 0x87:dyn_dop_evgv_xchg();break; + + // 'mov []/reg8/16/32,reg8/16/32' + case 0x88:dyn_dop_ebgb_mov();break; + case 0x89:dyn_dop_evgv_mov();break; + // 'mov reg8/16/32,[]/reg8/16/32' + case 0x8a:dyn_dop_gbeb_mov();break; + case 0x8b:dyn_dop_gvev_mov();break; + + // move segment register into memory or a 16bit register + case 0x8c:dyn_mov_ev_seg();break; + + // load effective address + case 0x8d: + dyn_get_modrm(); + dyn_fill_ea(FC_ADDR,false); + gen_mov_word_from_reg(FC_ADDR,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + break; + + // move a value from memory or a 16bit register into a segment register + case 0x8e:dyn_mov_seg_ev();break; + + // 'pop []' + case 0x8f:dyn_pop_ev();break; + + case 0x90: // nop + case 0x9b: // wait + case 0xf0: // lock + break; + + case 0x91:case 0x92:case 0x93:case 0x94:case 0x95:case 0x96:case 0x97: + dyn_xchg_ax(opcode&7); + break; + + // sign-extend al into ax/sign-extend ax into eax + case 0x98:dyn_cbw();break; + // sign-extend ax into dx:ax/sign-extend eax into edx:eax + case 0x99:dyn_cwd();break; + + case 0x9a:dyn_call_far_imm();goto finish_block; + + case 0x9c: // pushf + AcquireFlags(FMASK_TEST); + gen_call_function_I((void *)&CPU_PUSHF,decode.big_op); + dyn_check_exception(FC_RETOP); + break; + case 0x9d: // popf + gen_call_function_I((void *)&CPU_POPF,decode.big_op); + dyn_check_exception(FC_RETOP); + InvalidateFlags(); + break; + + case 0x9e:dyn_sahf();break; +// case 0x9f: LAHF missing + + // 'mov al/ax,[]' + case 0xa0: + dyn_mov_byte_al_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); + break; + case 0xa1: + dyn_mov_byte_ax_direct(decode.big_addr ? decode_fetchd() : decode_fetchw()); + break; + // 'mov [],al/ax' + case 0xa2: + dyn_mov_byte_direct_al(); + break; + case 0xa3: + dyn_mov_byte_direct_ax(decode.big_addr ? decode_fetchd() : decode_fetchw()); + break; + + +// case 0xa6 to 0xaf string operations, some missing + + // movsb/w/d + case 0xa4:dyn_string(STR_MOVSB);break; + case 0xa5:dyn_string(decode.big_op ? STR_MOVSD : STR_MOVSW);break; + + // stosb/w/d + case 0xaa:dyn_string(STR_STOSB);break; + case 0xab:dyn_string(decode.big_op ? STR_STOSD : STR_STOSW);break; + + // lodsb/w/d + case 0xac:dyn_string(STR_LODSB);break; + case 0xad:dyn_string(decode.big_op ? STR_LODSD : STR_LODSW);break; + + + // 'test reg8/16/32,imm8/16/32' + case 0xa8:dyn_dop_byte_imm(DOP_TEST,DRC_REG_EAX,0);break; + case 0xa9:dyn_dop_word_imm_old(DOP_TEST,DRC_REG_EAX,decode.big_op ? decode_fetchd() : decode_fetchw());break; + + // 'mov reg8/16/32,imm8/16/32' + case 0xb0:case 0xb1:case 0xb2:case 0xb3:case 0xb4:case 0xb5:case 0xb6:case 0xb7: + dyn_mov_byte_imm(opcode&3,(opcode>>2)&1,decode_fetchb()); + break; + case 0xb8:case 0xb9:case 0xba:case 0xbb:case 0xbc:case 0xbd:case 0xbe:case 0xbf: + dyn_mov_word_imm(opcode&7);break; + break; + + // 'shiftop []/reg8,imm8/1/cl' + case 0xc0:dyn_grp2_eb(grp2_imm);break; + case 0xd0:dyn_grp2_eb(grp2_1);break; + case 0xd2:dyn_grp2_eb(grp2_cl);break; + + // 'shiftop []/reg16/32,imm8/1/cl' + case 0xc1:dyn_grp2_ev(grp2_imm);break; + case 0xd1:dyn_grp2_ev(grp2_1);break; + case 0xd3:dyn_grp2_ev(grp2_cl);break; + + // retn [param] + case 0xc2:dyn_ret_near(decode_fetchw());goto finish_block; + case 0xc3:dyn_ret_near(0);goto finish_block; + + case 0xc4:dyn_load_seg_off_ea(DRC_SEG_ES);break; + case 0xc5:dyn_load_seg_off_ea(DRC_SEG_DS);break; + + // 'mov []/reg8/16/32,imm8/16/32' + case 0xc6:dyn_dop_ebib_mov();break; + case 0xc7:dyn_dop_eviv_mov();break; + + case 0xc8:dyn_enter();break; + case 0xc9:dyn_leave();break; + + // retf [param] + case 0xca:dyn_ret_far(decode_fetchw());goto finish_block; + case 0xcb:dyn_ret_far(0);goto finish_block; + + // int/iret + case 0xcd:dyn_interrupt(decode_fetchb());goto finish_block; + case 0xcf:dyn_iret();goto finish_block; + +// case 0xd4: AAM missing +// case 0xd5: AAD missing + +// case 0xd6: SALC missing +// case 0xd7: XLAT missing + + +#ifdef CPU_FPU + // floating point instructions + case 0xd8: + dyn_fpu_esc0(); + break; + case 0xd9: + dyn_fpu_esc1(); + break; + case 0xda: + dyn_fpu_esc2(); + break; + case 0xdb: + dyn_fpu_esc3(); + break; + case 0xdc: + dyn_fpu_esc4(); + break; + case 0xdd: + dyn_fpu_esc5(); + break; + case 0xde: + dyn_fpu_esc6(); + break; + case 0xdf: + dyn_fpu_esc7(); + break; +#endif + + + // loop instructions + case 0xe0:dyn_loop(LOOP_NE);goto finish_block; + case 0xe1:dyn_loop(LOOP_E);goto finish_block; + case 0xe2:dyn_loop(LOOP_NONE);goto finish_block; + case 0xe3:dyn_loop(LOOP_JCXZ);goto finish_block; + + + // 'in al/ax/eax,port_imm' + case 0xe4:dyn_read_port_byte_direct(decode_fetchb());break; + case 0xe5:dyn_read_port_word_direct(decode_fetchb());break; + // 'out port_imm,al/ax/eax' + case 0xe6:dyn_write_port_byte_direct(decode_fetchb());break; + case 0xe7:dyn_write_port_word_direct(decode_fetchb());break; + + // 'in al/ax/eax,port_dx' + case 0xec:dyn_read_port_byte();break; + case 0xed:dyn_read_port_word();break; + // 'out port_dx,al/ax/eax' + case 0xee:dyn_write_port_byte();break; + case 0xef:dyn_write_port_word();break; + + + // 'call near imm16/32' + case 0xe8: + dyn_call_near_imm(); + goto finish_block; + // 'jmp near imm16/32' + case 0xe9: + dyn_exit_link(decode.big_op ? (Bit32s)decode_fetchd() : (Bit16s)decode_fetchw()); + goto finish_block; + // 'jmp far' + case 0xea: + dyn_jmp_far_imm(); + goto finish_block; + // 'jmp short imm8' + case 0xeb: + dyn_exit_link((Bit8s)decode_fetchb()); + goto finish_block; + + + // repeat prefixes + case 0xf2: + decode.rep=REP_NZ; + goto restart_prefix; + case 0xf3: + decode.rep=REP_Z; + goto restart_prefix; + + case 0xf5: //CMC + gen_call_function_raw((void*)dynrec_cmc); + break; + case 0xf8: //CLC + gen_call_function_raw((void*)dynrec_clc); + break; + case 0xf9: //STC + gen_call_function_raw((void*)dynrec_stc); + break; + + case 0xf6:dyn_grp3_eb();break; + case 0xf7:dyn_grp3_ev();break; + + case 0xfa: //CLI + gen_call_function_raw((void *)&CPU_CLI); + if (cpu.pmode) dyn_check_exception(FC_RETOP); + break; + case 0xfb: //STI + gen_call_function_raw((void *)&CPU_STI); + if (cpu.pmode) dyn_check_exception(FC_RETOP); + if (max_opcodes<=0) max_opcodes=1; //Allow 1 extra opcode + break; + + case 0xfc: //CLD + gen_call_function_raw((void*)dynrec_cld); + break; + case 0xfd: //STD + gen_call_function_raw((void*)dynrec_std); + break; + + case 0xfe: + if (dyn_grp4_eb()) goto finish_block; + break; + case 0xff: + if (dyn_grp4_ev()) goto core_close_block; + break; + + default: +// DYN_LOG("Dynrec unhandled opcode %X",opcode); + goto illegalopcode; + } + } + // normal exit because the maximal number of opcodes has been reached + dyn_set_eip_end(); +core_close_block: + dyn_reduce_cycles(); + dyn_return(BR_Normal); + dyn_closeblock(); + goto finish_block; +illegalopcode: + // some unhandled opcode has been encountered + dyn_set_eip_last(); + dyn_reduce_cycles(); + dyn_return(BR_Opcode); // tell the core what happened + dyn_closeblock(); + goto finish_block; +finish_block: + + // setup the correct end-address + decode.page.index--; + decode.active_block->page.end=(Bit16u)decode.page.index; +// LOG_MSG("Created block size %d start %d end %d",decode.block->cache.size,decode.block->page.start,decode.block->page.end); + + return decode.block; +} diff --git a/src/cpu/core_dynrec/decoder_basic.h b/src/cpu/core_dynrec/decoder_basic.h new file mode 100644 index 0000000..b8f515b --- /dev/null +++ b/src/cpu/core_dynrec/decoder_basic.h @@ -0,0 +1,1103 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +/* + This file provides some definitions and basic level functions + that use code generating functions from risc_?.h + Important is the function call generation including parameter + loading, the effective address calculation and the memory + access functions. +*/ + + +// instructions that use one operand +enum SingleOps { + SOP_INC,SOP_DEC, + SOP_NOT,SOP_NEG, +}; + +// instructions that use two operand +enum DualOps { + DOP_ADD,DOP_ADC, + DOP_SUB,DOP_SBB, + DOP_CMP,DOP_XOR, + DOP_AND,DOP_OR, + DOP_TEST, + DOP_MOV, + DOP_XCHG, +}; + +// shift and rotate functions +enum ShiftOps { + SHIFT_ROL,SHIFT_ROR, + SHIFT_RCL,SHIFT_RCR, + SHIFT_SHL,SHIFT_SHR, + SHIFT_SAL,SHIFT_SAR, +}; + +// branch conditions +enum BranchTypes { + BR_O,BR_NO,BR_B,BR_NB, + BR_Z,BR_NZ,BR_BE,BR_NBE, + BR_S,BR_NS,BR_P,BR_NP, + BR_L,BR_NL,BR_LE,BR_NLE +}; + +// string instructions +enum StringOps { + STR_OUTSB=0,STR_OUTSW,STR_OUTSD, + STR_INSB=4,STR_INSW,STR_INSD, + STR_MOVSB=8,STR_MOVSW,STR_MOVSD, + STR_LODSB=12,STR_LODSW,STR_LODSD, + STR_STOSB=16,STR_STOSW,STR_STOSD, + STR_SCASB=20,STR_SCASW,STR_SCASD, + STR_CMPSB=24,STR_CMPSW,STR_CMPSD, +}; + +// repeat prefix type (for string operations) +enum REP_Type { + REP_NONE=0,REP_NZ,REP_Z +}; + +// loop type +enum LoopTypes { + LOOP_NONE,LOOP_NE,LOOP_E,LOOP_JCXZ +}; + +// rotate operand type +enum grp2_types { + grp2_1,grp2_imm,grp2_cl, +}; + +// opcode mapping for group1 instructions +static DualOps grp1_table[8]={ + DOP_ADD,DOP_OR,DOP_ADC,DOP_SBB,DOP_AND,DOP_SUB,DOP_XOR,DOP_CMP +}; + + +// decoding information used during translation of a code block +static struct DynDecode { + PhysPt code; // pointer to next byte in the instruction stream + PhysPt code_start; // pointer to the start of the current code block + PhysPt op_start; // pointer to the start of the current instruction + bool big_op; // operand modifier + bool big_addr; // address modifier + REP_Type rep; // current repeat prefix + Bitu cycles; // number cycles used by currently translated code + bool seg_prefix_used; // segment overridden + Bit8u seg_prefix; // segment prefix (if seg_prefix_used==true) + + // block that contains the first instruction translated + CacheBlockDynRec * block; + // block that contains the current byte of the instruction stream + CacheBlockDynRec * active_block; + + // the active page (containing the current byte of the instruction stream) + struct { + CodePageHandlerDynRec * code; + Bitu index; // index to the current byte of the instruction stream + Bit8u * wmap; // write map that indicates code presence for every byte of this page + Bit8u * invmap; // invalidation map + Bitu first; // page number + } page; + + // modrm state of the current instruction (if used) + struct { + Bitu val; + Bitu mod; + Bitu rm; + Bitu reg; + } modrm; +} decode; + + +static bool MakeCodePage(Bitu lin_addr,CodePageHandlerDynRec * &cph) { + Bit8u rdval; + //Ensure page contains memory: + if (GCC_UNLIKELY(mem_readb_checked_x86(lin_addr,&rdval))) return true; + + Bitu lin_page=lin_addr >> 12; + + PageHandler * handler=paging.tlb.handler[lin_page]; + if (handler->flags & PFLAG_HASCODE) { + // this is a codepage handler, and the one that we're looking for + cph=(CodePageHandlerDynRec *)handler; + return false; + } + if (handler->flags & PFLAG_NOCODE) { + LOG_MSG("DYNREC:Can't run code in this page"); + cph=0; + return false; + } + Bitu phys_page=lin_page; + // find the physical page that the linear page is mapped to + if (!PAGING_MakePhysPage(phys_page)) { + LOG_MSG("DYNREC:Can't find physpage"); + cph=0; + return false; + } + // find a free CodePage + if (!cache.free_pages) { + if (cache.used_pages!=decode.page.code) cache.used_pages->ClearRelease(); + else { + // try another page to avoid clearing our source-crosspage + if ((cache.used_pages->next) && (cache.used_pages->next!=decode.page.code)) + cache.used_pages->next->ClearRelease(); + else { + LOG_MSG("DYNREC:Invalid cache links"); + cache.used_pages->ClearRelease(); + } + } + } + CodePageHandlerDynRec * cpagehandler=cache.free_pages; + cache.free_pages=cache.free_pages->next; + + // adjust previous and next page pointer + cpagehandler->prev=cache.last_page; + cpagehandler->next=0; + if (cache.last_page) cache.last_page->next=cpagehandler; + cache.last_page=cpagehandler; + if (!cache.used_pages) cache.used_pages=cpagehandler; + + // initialize the code page handler and add the handler to the memory page + cpagehandler->SetupAt(phys_page,handler); + MEM_SetPageHandler(phys_page,1,cpagehandler); + PAGING_UnlinkPages(lin_page,1); + cph=cpagehandler; + return false; +} + +static void decode_advancepage(void) { + // Advance to the next page + decode.active_block->page.end=4095; + // trigger possible page fault here + decode.page.first++; + Bitu faddr=decode.page.first << 12; + mem_readb(faddr); + MakeCodePage(faddr,decode.page.code); + CacheBlockDynRec * newblock=cache_getblock(); + decode.active_block->crossblock=newblock; + newblock->crossblock=decode.active_block; + decode.active_block=newblock; + decode.active_block->page.start=0; + decode.page.code->AddCrossBlock(decode.active_block); + decode.page.wmap=decode.page.code->write_map; + decode.page.invmap=decode.page.code->invalidation_map; + decode.page.index=0; +} + +// fetch the next byte of the instruction stream +static Bit8u decode_fetchb(void) { + if (GCC_UNLIKELY(decode.page.index>=4096)) { + decode_advancepage(); + } + decode.page.wmap[decode.page.index]+=0x01; + decode.page.index++; + decode.code+=1; + return mem_readb(decode.code-1); +} +// fetch the next word of the instruction stream +static Bit16u decode_fetchw(void) { + if (GCC_UNLIKELY(decode.page.index>=4095)) { + Bit16u val=decode_fetchb(); + val|=decode_fetchb() << 8; + return val; + } + *(Bit16u *)&decode.page.wmap[decode.page.index]+=0x0101; + decode.code+=2;decode.page.index+=2; + return mem_readw(decode.code-2); +} +// fetch the next dword of the instruction stream +static Bit32u decode_fetchd(void) { + if (GCC_UNLIKELY(decode.page.index>=4093)) { + Bit32u val=decode_fetchb(); + val|=decode_fetchb() << 8; + val|=decode_fetchb() << 16; + val|=decode_fetchb() << 24; + return val; + /* Advance to the next page */ + } + *(Bit32u *)&decode.page.wmap[decode.page.index]+=0x01010101; + decode.code+=4;decode.page.index+=4; + return mem_readd(decode.code-4); +} + +#define START_WMMEM 64 + +// adjust writemap mask to care for map holes due to special +// codefetch functions +static void INLINE decode_increase_wmapmask(Bitu size) { + Bitu mapidx; + CacheBlockDynRec* activecb=decode.active_block; + if (GCC_UNLIKELY(!activecb->cache.wmapmask)) { + // no mask memory yet allocated, start with a small buffer + activecb->cache.wmapmask=(Bit8u*)malloc(START_WMMEM); + memset(activecb->cache.wmapmask,0,START_WMMEM); + activecb->cache.maskstart=decode.page.index; // start of buffer is current code position + activecb->cache.masklen=START_WMMEM; + mapidx=0; + } else { + mapidx=decode.page.index-activecb->cache.maskstart; + if (GCC_UNLIKELY(mapidx+size>=activecb->cache.masklen)) { + // mask buffer too small, increase + Bitu newmasklen=activecb->cache.masklen*4; + if (newmasklencache.wmapmask,activecb->cache.masklen); + free(activecb->cache.wmapmask); + activecb->cache.wmapmask=tempmem; + activecb->cache.masklen=newmasklen; + } + } + // update mask entries + switch (size) { + case 1 : activecb->cache.wmapmask[mapidx]+=0x01; break; + case 2 : (*(Bit16u*)&activecb->cache.wmapmask[mapidx])+=0x0101; break; + case 4 : (*(Bit32u*)&activecb->cache.wmapmask[mapidx])+=0x01010101; break; + } +} + +// fetch a byte, val points to the code location if possible, +// otherwise val contains the current value read from the position +static bool decode_fetchb_imm(Bitu & val) { + if (GCC_UNLIKELY(decode.page.index>=4096)) { + decode_advancepage(); + } + Bitu index=(decode.code>>12); + // see if position is directly accessible + if (paging.tlb.read[index]) { + val=(Bitu)(paging.tlb.read[index]+decode.code); + decode_increase_wmapmask(1); + decode.code++; + decode.page.index++; + return true; + } + // not directly accessible, just fetch the value + val=(Bit32u)decode_fetchb(); + return false; +} + +// fetch a word, val points to the code location if possible, +// otherwise val contains the current value read from the position +static bool decode_fetchw_imm(Bitu & val) { + if (decode.page.index<4095) { + Bitu index=(decode.code>>12); + // see if position is directly accessible + if (paging.tlb.read[index]) { + val=(Bitu)(paging.tlb.read[index]+decode.code); + decode_increase_wmapmask(2); + decode.code+=2; + decode.page.index+=2; + return true; + } + } + // not directly accessible, just fetch the value + val=decode_fetchw(); + return false; +} + +// fetch a dword, val points to the code location if possible, +// otherwise val contains the current value read from the position +static bool decode_fetchd_imm(Bitu & val) { + if (decode.page.index<4093) { + Bitu index=(decode.code>>12); + // see if position is directly accessible + if (paging.tlb.read[index]) { + val=(Bitu)(paging.tlb.read[index]+decode.code); + decode_increase_wmapmask(4); + decode.code+=4; + decode.page.index+=4; + return true; + } + } + // not directly accessible, just fetch the value + val=decode_fetchd(); + return false; +} + + +// 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); +} + + + +// adjust CPU_Cycles value +static void dyn_reduce_cycles(void) { + if (!decode.cycles) decode.cycles++; + gen_sub_direct_word(&CPU_Cycles,decode.cycles,true); +} + + +// set reg to the start of the next instruction +// set reg_eip to the start of the current instruction +static INLINE void dyn_set_eip_last_end(HostReg reg) { + gen_mov_word_to_reg(reg,®_eip,true); + gen_add_imm(reg,(Bit32u)(decode.code-decode.code_start)); + gen_add_direct_word(®_eip,decode.op_start-decode.code_start,decode.big_op); +} + +// set reg_eip to the start of the current instruction +static INLINE void dyn_set_eip_last(void) { + gen_add_direct_word(®_eip,decode.op_start-decode.code_start,cpu.code.big); +} + +// set reg_eip to the start of the next instruction +static INLINE void dyn_set_eip_end(void) { + gen_add_direct_word(®_eip,decode.code-decode.code_start,cpu.code.big); +} + +// 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_add_imm(reg,(Bit32u)(decode.code-decode.code_start+imm)); + if (!decode.big_op) gen_extend_word(false,reg); +} + + + +// the following functions generate function calls +// parameters are loaded by generating code using gen_load_param_ which +// is architecture dependent +// R=host register; I=32bit immediate value; A=address value; m=memory + +static DRC_PTR_SIZE_IM INLINE gen_call_function_R(void * func,Bitu op) { + gen_load_param_reg(op,0); + return gen_call_function_setup(func, 1); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_R3(void * func,Bitu op) { + gen_load_param_reg(op,2); + return gen_call_function_setup(func, 3, true); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_RI(void * func,Bitu op1,Bitu op2) { + gen_load_param_imm(op2,1); + gen_load_param_reg(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_RA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { + gen_load_param_addr(op2,1); + gen_load_param_reg(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_RR(void * func,Bitu op1,Bitu op2) { + gen_load_param_reg(op2,1); + gen_load_param_reg(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_IR(void * func,Bitu op1,Bitu op2) { + gen_load_param_reg(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_I(void * func,Bitu op) { + gen_load_param_imm(op,0); + return gen_call_function_setup(func, 1); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_II(void * func,Bitu op1,Bitu op2) { + gen_load_param_imm(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_III(void * func,Bitu op1,Bitu op2,Bitu op3) { + gen_load_param_imm(op3,2); + gen_load_param_imm(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 3); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_IA(void * func,Bitu op1,DRC_PTR_SIZE_IM op2) { + gen_load_param_addr(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 2); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_IIR(void * func,Bitu op1,Bitu op2,Bitu op3) { + gen_load_param_reg(op3,2); + gen_load_param_imm(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 3); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_IIIR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { + gen_load_param_reg(op4,3); + gen_load_param_imm(op3,2); + gen_load_param_imm(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 4); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_IRRR(void * func,Bitu op1,Bitu op2,Bitu op3,Bitu op4) { + gen_load_param_reg(op4,3); + gen_load_param_reg(op3,2); + gen_load_param_reg(op2,1); + gen_load_param_imm(op1,0); + return gen_call_function_setup(func, 4); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_m(void * func,Bitu op) { + gen_load_param_mem(op,2); + return gen_call_function_setup(func, 3, true); +} + +static DRC_PTR_SIZE_IM INLINE gen_call_function_mm(void * func,Bitu op1,Bitu op2) { + gen_load_param_mem(op2,3); + gen_load_param_mem(op1,2); + return gen_call_function_setup(func, 4, true); +} + + + +enum save_info_type {exception, cycle_check, string_break}; + + +// function that is called on exceptions +static BlockReturn DynRunException(Bit32u eip_add,Bit32u cycle_sub) { + reg_eip+=eip_add; + CPU_Cycles-=cycle_sub; + if (cpu.exception.which==SMC_CURRENT_BLOCK) return BR_SMCBlock; + CPU_Exception(cpu.exception.which,cpu.exception.error); + return BR_Normal; +} + + +// array with information about code that is generated at the +// end of a cache block because it is rarely reached (like exceptions) +static struct { + save_info_type type; + DRC_PTR_SIZE_IM branch_pos; + Bit32u eip_change; + Bitu cycles; +} save_info_dynrec[512]; + +Bitu used_save_info_dynrec=0; + + +// return from current block, with returncode +static void dyn_return(BlockReturn retcode,bool ret_exception=false) { + if (!ret_exception) { + gen_mov_dword_to_reg_imm(FC_RETOP,retcode); + } + gen_return_function(); +} + +static void dyn_run_code(void) { + gen_run_code(); + gen_return_function(); +} + +// fill in code at the end of the block that contains rarely-executed code +// which is executed conditionally (like exceptions) +static void dyn_fill_blocks(void) { + for (Bitu sct=0; sct>12); + if (paging.tlb.read[index]) { + *((Bit8u*)(&core_dynrec.readdata))=host_readb(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readb_checked(address, &uval); + *((Bit8u*)(&core_dynrec.readdata))=(Bit8u)uval; + return retval; + } +} + +bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) DRC_FC; +bool DRC_CALL_CONV mem_writeb_checked_drc(PhysPt address,Bit8u val) { + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writeb(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writeb_checked(address,val); +} + +bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) DRC_FC; +bool DRC_CALL_CONV mem_readw_checked_drc(PhysPt address) { +#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) + if (!(address & 1)) { +#else + if ((address & 0xfff)<0xfff) { +#endif + Bitu index=(address>>12); + if (paging.tlb.read[index]) { + *((Bit16u*)(&core_dynrec.readdata))=host_readw(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readw_checked(address, &uval); + *((Bit16u*)(&core_dynrec.readdata))=(Bit16u)uval; + return retval; + } + } else return mem_unalignedreadw_checked_x86(address, ((Bit16u*)(&core_dynrec.readdata))); +} + +bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) DRC_FC; +bool DRC_CALL_CONV mem_readd_checked_drc(PhysPt address) { +#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) + if (!(address & 3)) { +#else + if ((address & 0xfff)<0xffd) { +#endif + Bitu index=(address>>12); + if (paging.tlb.read[index]) { + *((Bit32u*)(&core_dynrec.readdata))=host_readd(paging.tlb.read[index]+address); + return false; + } else { + Bitu uval; + bool retval; + retval=paging.tlb.handler[index]->readd_checked(address, &uval); + *((Bit32u*)(&core_dynrec.readdata))=(Bit32u)uval; + return retval; + } + } else return mem_unalignedreadd_checked_x86(address, ((Bit32u*)(&core_dynrec.readdata))); +} + +bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) DRC_FC; +bool DRC_CALL_CONV mem_writew_checked_drc(PhysPt address,Bit16u val) { +#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) + if (!(address & 1)) { +#else + if ((address & 0xfff)<0xfff) { +#endif + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writew(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writew_checked(address,val); + } else return mem_unalignedwritew_checked_x86(address,val); +} + +bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) DRC_FC; +bool DRC_CALL_CONV mem_writed_checked_drc(PhysPt address,Bit32u val) { +#if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY) + if (!(address & 3)) { +#else + if ((address & 0xfff)<0xffd) { +#endif + Bitu index=(address>>12); + if (paging.tlb.write[index]) { + host_writed(paging.tlb.write[index]+address,val); + return false; + } else return paging.tlb.handler[index]->writed_checked(address,val); + } else return mem_unalignedwrited_checked_x86(address,val); +} + + +// functions that enable access to the memory + +// read a byte from a given address and store it in reg_dst +static void dyn_read_byte(HostReg reg_addr,HostReg reg_dst) { + gen_mov_regs(FC_OP1,reg_addr); + gen_call_function_raw((void *)&mem_readb_checked_drc); + dyn_check_exception(FC_RETOP); + gen_mov_byte_to_reg_low(reg_dst,&core_dynrec.readdata); +} +static void dyn_read_byte_canuseword(HostReg reg_addr,HostReg reg_dst) { + gen_mov_regs(FC_OP1,reg_addr); + gen_call_function_raw((void *)&mem_readb_checked_drc); + dyn_check_exception(FC_RETOP); + gen_mov_byte_to_reg_low_canuseword(reg_dst,&core_dynrec.readdata); +} + +// write a byte from reg_val into the memory given by the address +static void dyn_write_byte(HostReg reg_addr,HostReg reg_val) { + gen_mov_regs(FC_OP2,reg_val); + gen_mov_regs(FC_OP1,reg_addr); + gen_call_function_raw((void *)&mem_writeb_checked_drc); + dyn_check_exception(FC_RETOP); +} + +// read a 32bit (dword=true) or 16bit (dword=false) value +// from a given address and store it in reg_dst +static void dyn_read_word(HostReg reg_addr,HostReg reg_dst,bool dword) { + gen_mov_regs(FC_OP1,reg_addr); + if (dword) gen_call_function_raw((void *)&mem_readd_checked_drc); + else gen_call_function_raw((void *)&mem_readw_checked_drc); + dyn_check_exception(FC_RETOP); + gen_mov_word_to_reg(reg_dst,&core_dynrec.readdata,dword); +} + +// write a 32bit (dword=true) or 16bit (dword=false) value +// from reg_val into the memory given by the address +static void dyn_write_word(HostReg reg_addr,HostReg reg_val,bool dword) { +// if (!dword) gen_extend_word(false,reg_val); + gen_mov_regs(FC_OP2,reg_val); + gen_mov_regs(FC_OP1,reg_addr); + if (dword) gen_call_function_raw((void *)&mem_writed_checked_drc); + else gen_call_function_raw((void *)&mem_writew_checked_drc); + dyn_check_exception(FC_RETOP); +} + + + +// effective address calculation helper, op2 has to be present! +// loads op1 into ea_reg and adds the scaled op2 and the immediate to it +static void dyn_lea(HostReg ea_reg,void* op1,void* op2,Bitu scale,Bits imm) { + if (scale || imm) { + if (op1!=NULL) { + gen_mov_word_to_reg(ea_reg,op1,true); + gen_mov_word_to_reg(TEMP_REG_DRC,op2,true); + + gen_lea(ea_reg,TEMP_REG_DRC,scale,imm); + } else { + gen_mov_word_to_reg(ea_reg,op2,true); + gen_lea(ea_reg,scale,imm); + } + } else { + gen_mov_word_to_reg(ea_reg,op2,true); + if (op1!=NULL) gen_add(ea_reg,op1); + } +} + +// calculate the effective address and store it in ea_reg +static void dyn_fill_ea(HostReg ea_reg,bool addseg=true) { + Bit8u seg_base=DRC_SEG_DS; + if (!decode.big_addr) { + Bits imm; + switch (decode.modrm.mod) { + case 0:imm=0;break; + case 1:imm=(Bit8s)decode_fetchb();break; + case 2:imm=(Bit16s)decode_fetchw();break; + } + switch (decode.modrm.rm) { + case 0:// BX+SI + dyn_lea(ea_reg,DRCD_REG(DRC_REG_EBX),DRCD_REG(DRC_REG_ESI),0,imm); + break; + case 1:// BX+DI + dyn_lea(ea_reg,DRCD_REG(DRC_REG_EBX),DRCD_REG(DRC_REG_EDI),0,imm); + break; + case 2:// BP+SI + dyn_lea(ea_reg,DRCD_REG(DRC_REG_EBP),DRCD_REG(DRC_REG_ESI),0,imm); + seg_base=DRC_SEG_SS; + break; + case 3:// BP+DI + dyn_lea(ea_reg,DRCD_REG(DRC_REG_EBP),DRCD_REG(DRC_REG_EDI),0,imm); + seg_base=DRC_SEG_SS; + break; + case 4:// SI + gen_mov_word_to_reg(ea_reg,DRCD_REG(DRC_REG_ESI),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + break; + case 5:// DI + gen_mov_word_to_reg(ea_reg,DRCD_REG(DRC_REG_EDI),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + break; + case 6:// imm/BP + if (!decode.modrm.mod) { + imm=decode_fetchw(); + gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); + goto skip_extend_word; + } else { + gen_mov_word_to_reg(ea_reg,DRCD_REG(DRC_REG_EBP),true); + gen_add_imm(ea_reg,(Bit32u)imm); + seg_base=DRC_SEG_SS; + } + break; + case 7: // BX + gen_mov_word_to_reg(ea_reg,DRCD_REG(DRC_REG_EBX),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + break; + } + // zero out the high 16bit so ea_reg can be used as full register + gen_extend_word(false,ea_reg); +skip_extend_word: + if (addseg) { + // add the physical segment value if requested + gen_add(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base)); + } + } else { + Bits imm=0; + Bit8u base_reg; + Bit8u scaled_reg; + Bitu scale=0; + switch (decode.modrm.rm) { + case 0:base_reg=DRC_REG_EAX;break; + case 1:base_reg=DRC_REG_ECX;break; + case 2:base_reg=DRC_REG_EDX;break; + case 3:base_reg=DRC_REG_EBX;break; + case 4: // SIB + { + Bitu sib=decode_fetchb(); + bool scaled_reg_used=false; + static Bit8u scaledtable[8]={ + DRC_REG_EAX,DRC_REG_ECX,DRC_REG_EDX,DRC_REG_EBX, + 0,DRC_REG_EBP,DRC_REG_ESI,DRC_REG_EDI + }; + // see if scaling should be used and which register is to be scaled in this case + if (((sib >> 3) &7)!=4) scaled_reg_used=true; + scaled_reg=scaledtable[(sib >> 3) &7]; + scale=(sib >> 6); + + switch (sib & 7) { + case 0:base_reg=DRC_REG_EAX;break; + case 1:base_reg=DRC_REG_ECX;break; + case 2:base_reg=DRC_REG_EDX;break; + case 3:base_reg=DRC_REG_EBX;break; + case 4:base_reg=DRC_REG_ESP;seg_base=DRC_SEG_SS;break; + case 5: + if (decode.modrm.mod) { + base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; + } else { + // no basereg, maybe scalereg + Bitu val; + // try to get a pointer to the next dword code position + if (decode_fetchd_imm(val)) { + // succeeded, use the pointer to avoid code invalidation + if (!addseg) { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,(void*)val,true); + } else { + dyn_lea(ea_reg,NULL,DRCD_REG(scaled_reg),scale,0); + gen_add(ea_reg,(void*)val); + } + } else { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + } else { + dyn_lea(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),DRCD_REG(scaled_reg),scale,0); + } + gen_add(ea_reg,(void*)val); + } + return; + } + // couldn't get a pointer, use the current value + imm=(Bit32s)val; + + if (!addseg) { + if (!scaled_reg_used) { + gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); + } else { + dyn_lea(ea_reg,NULL,DRCD_REG(scaled_reg),scale,imm); + } + } else { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + } else { + dyn_lea(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),DRCD_REG(scaled_reg),scale,imm); + } + } + + return; + } + break; + case 6:base_reg=DRC_REG_ESI;break; + case 7:base_reg=DRC_REG_EDI;break; + } + // basereg, maybe scalereg + switch (decode.modrm.mod) { + case 1: + imm=(Bit8s)decode_fetchb(); + break; + case 2: { + Bitu val; + // try to get a pointer to the next dword code position + if (decode_fetchd_imm(val)) { + // succeeded, use the pointer to avoid code invalidation + if (!addseg) { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_REG(base_reg),true); + gen_add(ea_reg,(void*)val); + } else { + dyn_lea(ea_reg,DRCD_REG(base_reg),DRCD_REG(scaled_reg),scale,0); + gen_add(ea_reg,(void*)val); + } + } else { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + } else { + dyn_lea(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),DRCD_REG(scaled_reg),scale,0); + } + gen_add(ea_reg,DRCD_REG(base_reg)); + gen_add(ea_reg,(void*)val); + } + return; + } + // couldn't get a pointer, use the current value + imm=(Bit32s)val; + break; + } + } + + if (!addseg) { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_REG(base_reg),true); + gen_add_imm(ea_reg,(Bit32u)imm); + } else { + dyn_lea(ea_reg,DRCD_REG(base_reg),DRCD_REG(scaled_reg),scale,imm); + } + } else { + if (!scaled_reg_used) { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + gen_add(ea_reg,DRCD_REG(base_reg)); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + } else { + dyn_lea(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),DRCD_REG(scaled_reg),scale,imm); + gen_add(ea_reg,DRCD_REG(base_reg)); + } + } + + return; + } + break; // SIB Break + case 5: + if (decode.modrm.mod) { + base_reg=DRC_REG_EBP;seg_base=DRC_SEG_SS; + } else { + // no base, no scalereg + + imm=(Bit32s)decode_fetchd(); + if (!addseg) { + gen_mov_dword_to_reg_imm(ea_reg,(Bit32u)imm); + } else { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + } + + return; + } + break; + case 6:base_reg=DRC_REG_ESI;break; + case 7:base_reg=DRC_REG_EDI;break; + } + + // no scalereg, but basereg + + switch (decode.modrm.mod) { + case 1: + imm=(Bit8s)decode_fetchb(); + break; + case 2: { + Bitu val; + // try to get a pointer to the next dword code position + if (decode_fetchd_imm(val)) { + // succeeded, use the pointer to avoid code invalidation + if (!addseg) { + gen_mov_word_to_reg(ea_reg,DRCD_REG(base_reg),true); + gen_add(ea_reg,(void*)val); + } else { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + gen_add(ea_reg,DRCD_REG(base_reg)); + gen_add(ea_reg,(void*)val); + } + return; + } + // couldn't get a pointer, use the current value + imm=(Bit32s)val; + break; + } + } + + if (!addseg) { + gen_mov_word_to_reg(ea_reg,DRCD_REG(base_reg),true); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + } else { + gen_mov_word_to_reg(ea_reg,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : seg_base),true); + gen_add(ea_reg,DRCD_REG(base_reg)); + if (imm) gen_add_imm(ea_reg,(Bit32u)imm); + } + } +} + + + +// add code that checks if port access is allowed +// the port is given in a register +static void dyn_add_iocheck(HostReg reg_port,Bitu access_size) { + if (cpu.pmode) { + gen_call_function_RI((void *)&CPU_IO_Exception,reg_port,access_size); + dyn_check_exception(FC_RETOP); + } +} + +// add code that checks if port access is allowed +// the port is a constant +static void dyn_add_iocheck_var(Bit8u accessed_port,Bitu access_size) { + if (cpu.pmode) { + gen_call_function_II((void *)&CPU_IO_Exception,accessed_port,access_size); + dyn_check_exception(FC_RETOP); + } +} + + + +// save back the address register +static void gen_protect_addr_reg(void) { +#ifdef DRC_PROTECT_ADDR_REG + gen_mov_word_from_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); +#endif +} + +// restore the address register +static void gen_restore_addr_reg(void) { +#ifdef DRC_PROTECT_ADDR_REG + gen_mov_word_to_reg(FC_ADDR,&core_dynrec.protected_regs[FC_ADDR],true); +#endif +} + +// save back an arbitrary register +static void gen_protect_reg(HostReg reg) { + gen_mov_word_from_reg(reg,&core_dynrec.protected_regs[reg],true); +} + +// restore an arbitrary register +static void gen_restore_reg(HostReg reg) { + gen_mov_word_to_reg(reg,&core_dynrec.protected_regs[reg],true); +} + +// restore an arbitrary register into a different register +static void gen_restore_reg(HostReg reg,HostReg dest_reg) { + gen_mov_word_to_reg(dest_reg,&core_dynrec.protected_regs[reg],true); +} + + + +// flags optimization functions +// they try to find out if a function can be replaced by another +// one that does not generate any flags at all + +static Bitu mf_functions_num=0; +static struct { + Bit8u* pos; + void* fct_ptr; + Bitu ftype; +} mf_functions[64]; + +static void InitFlagsOptimization(void) { + mf_functions_num=0; +} + +// replace all queued functions with their simpler variants +// because the current instruction destroys all condition flags and +// the flags are not required before +static void InvalidateFlags(void) { +#ifdef DRC_FLAGS_INVALIDATION + for (Bitu ct=0; ct>2)&1)); + dyn_dop_byte_gencall(op); + + if ((op!=DOP_CMP) && (op!=DOP_TEST)) { + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_RETOP); + } + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + gen_mov_byte_to_reg_low_canuseword(FC_OP2,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + dyn_dop_byte_gencall(op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_dop_ebgb_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + dyn_write_byte(FC_ADDR,FC_TMP_BA1); + } else { + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_dop_ebib_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); + dyn_write_byte(FC_ADDR,FC_TMP_BA1); + } else { + gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,decode_fetchb()); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_dop_ebgb_xchg(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_byte(FC_ADDR,FC_TMP_BA1); + gen_mov_byte_to_reg_low(FC_TMP_BA2,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_TMP_BA2); + } else { + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + gen_mov_byte_to_reg_low(FC_TMP_BA2,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + gen_mov_byte_from_reg_low(FC_TMP_BA2,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_dop_gbeb(DualOps op) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_byte_canuseword(FC_ADDR,FC_OP2); + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + dyn_dop_byte_gencall(op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP2,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + dyn_dop_byte_gencall(op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + } +} + +static void dyn_dop_gbeb_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_byte(FC_ADDR,FC_TMP_BA1); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + } else { + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.reg&3,(decode.modrm.reg>>2)&1)); + } +} + +static void dyn_dop_evgv(DualOps op) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + gen_protect_addr_reg(); + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + +static void dyn_dop_evgv_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + +static void dyn_dop_eviv_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); + else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); + dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); + } else { + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,decode_fetchd()); + else gen_mov_word_to_reg_imm(FC_OP1,decode_fetchw()); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + +static void dyn_dop_evgv_xchg(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); + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + + gen_protect_reg(FC_OP1); + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_OP2,decode.big_op); + gen_restore_reg(FC_OP1); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + +static void dyn_xchg_ax(Bit8u reg) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,decode.big_op),decode.big_op); + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP2,DRCD_REG_WORD(DRC_REG_EAX,decode.big_op),decode.big_op); +} + +static void dyn_dop_gvev(DualOps op) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) { + gen_restore_addr_reg(); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } + } else { + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } +} + +static void dyn_dop_gvev_mov(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } +} + +static void dyn_dop_byte_imm(DualOps op,Bit8u reg,Bit8u idx) { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(reg,idx)); + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); + dyn_dop_byte_gencall(op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(reg,idx)); +} + +static void dyn_dop_byte_imm_mem(DualOps op,Bit8u reg,Bit8u idx) { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(reg,idx)); + Bitu val; + if (decode_fetchb_imm(val)) { + gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); + } else { + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,(Bit8u)val); + } + dyn_dop_byte_gencall(op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(reg,idx)); +} + +static void dyn_prep_word_imm(Bit8u reg) { + Bitu val; + if (decode.big_op) { + if (decode_fetchd_imm(val)) { + gen_mov_word_to_reg(FC_OP2,(void*)val,true); + return; + } + } else { + if (decode_fetchw_imm(val)) { + gen_mov_word_to_reg(FC_OP2,(void*)val,false); + return; + } + } + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)val); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)val); +} + +static void dyn_dop_word_imm(DualOps op,Bit8u reg) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + dyn_prep_word_imm(reg); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); +} + +static void dyn_dop_word_imm_old(DualOps op,Bit8u reg,Bitu imm) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); + dyn_dop_word_gencall(op,decode.big_op); + if ((op!=DOP_CMP) && (op!=DOP_TEST)) gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); +} + +static void dyn_mov_byte_imm(Bit8u reg,Bit8u idx,Bit8u imm) { + gen_mov_byte_to_reg_low_imm(FC_TMP_BA1,imm); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(reg,idx)); +} + +static void dyn_mov_word_imm(Bit8u reg) { + Bitu val; + if (decode.big_op) { + if (decode_fetchd_imm(val)) { + gen_mov_word_to_reg(FC_OP1,(void*)val,true); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(reg,true),true); + return; + } + } else { + if (decode_fetchw_imm(val)) { + gen_mov_word_to_reg(FC_OP1,(void*)val,false); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(reg,false),false); + return; + } + } + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)val); + else gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)val); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); +} + + +static void dyn_sop_word(SingleOps op,Bit8u reg) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + dyn_sop_word_gencall(op,decode.big_op); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); +} + + +static void dyn_mov_byte_al_direct(Bitu imm) { + gen_mov_word_to_reg(FC_ADDR,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS),true); + gen_add_imm(FC_ADDR,imm); + dyn_read_byte(FC_ADDR,FC_TMP_BA1); + gen_mov_byte_from_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(DRC_REG_EAX,0)); +} + +static void dyn_mov_byte_ax_direct(Bitu imm) { + gen_mov_word_to_reg(FC_ADDR,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS),true); + gen_add_imm(FC_ADDR,imm); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,decode.big_op),decode.big_op); +} + +static void dyn_mov_byte_direct_al() { + gen_mov_word_to_reg(FC_ADDR,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS),true); + if (decode.big_addr) { + Bitu val; + if (decode_fetchd_imm(val)) { + gen_add(FC_ADDR,(void*)val); + } else { + gen_add_imm(FC_ADDR,(Bit32u)val); + } + } else { + gen_add_imm(FC_ADDR,decode_fetchw()); + } + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(DRC_REG_EAX,0)); + dyn_write_byte(FC_ADDR,FC_TMP_BA1); +} + +static void dyn_mov_byte_direct_ax(Bitu imm) { + gen_mov_word_to_reg(FC_ADDR,DRCD_SEG_PHYS(decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS),true); + gen_add_imm(FC_ADDR,imm); + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,decode.big_op),decode.big_op); + dyn_write_word(FC_ADDR,FC_OP1,decode.big_op); +} + + +static void dyn_movx_ev_gb(bool sign) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_byte(FC_ADDR,FC_TMP_BA1); + gen_extend_byte(sign,FC_TMP_BA1); + gen_mov_word_from_reg(FC_TMP_BA1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } else { + gen_mov_byte_to_reg_low(FC_TMP_BA1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + gen_extend_byte(sign,FC_TMP_BA1); + gen_mov_word_from_reg(FC_TMP_BA1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } +} + +static void dyn_movx_ev_gw(bool sign) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_OP1,false); + gen_extend_word(sign,FC_OP1); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,false),false); + gen_extend_word(sign,FC_OP1); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } +} + + +static void dyn_mov_ev_seg(void) { + dyn_get_modrm(); + gen_mov_word_to_reg(FC_OP1,DRCD_SEG_VAL(decode.modrm.reg),false); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_write_word(FC_ADDR,FC_OP1,false); + } else { + if (decode.big_op) gen_extend_word(false,FC_OP1); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + + +static void dyn_push_seg(Bit8u seg) { + gen_mov_word_to_reg(FC_OP1,DRCD_SEG_VAL(seg),false); + if (decode.big_op) { + gen_extend_word(false,FC_OP1); + gen_call_function_raw((void*)&dynrec_push_dword); + } else { + gen_call_function_raw((void*)&dynrec_push_word); + } +} + +static void dyn_pop_seg(Bit8u seg) { + gen_call_function_II((void *)&CPU_PopSeg,seg,decode.big_op); + if (cpu.pmode) dyn_check_exception(FC_RETOP); +} + +static void dyn_push_reg(Bit8u reg) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); + if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); + else gen_call_function_raw((void*)&dynrec_push_word); +} + +static void dyn_pop_reg(Bit8u reg) { + if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); + else gen_call_function_raw((void*)&dynrec_pop_word); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(reg,decode.big_op),decode.big_op); +} + +static void dyn_push_byte_imm(Bit8s imm) { + gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); + if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); + else gen_call_function_raw((void*)&dynrec_push_word); +} + +static void dyn_push_word_imm(Bitu imm) { + if (decode.big_op) { + gen_mov_dword_to_reg_imm(FC_OP1,imm); + gen_call_function_raw((void*)&dynrec_push_dword); + } else { + gen_mov_word_to_reg_imm(FC_OP1,(Bit16u)imm); + gen_call_function_raw((void*)&dynrec_push_word); + } +} + +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 */ + 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); + } else { + if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); + else gen_call_function_raw((void*)&dynrec_pop_word); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + + +static void dyn_segprefix(Bit8u seg) { + if (GCC_UNLIKELY(decode.seg_prefix_used)) IllegalOptionDynrec("dyn_segprefix"); + decode.seg_prefix=seg; + decode.seg_prefix_used=true; +} + + static void dyn_mov_seg_ev(void) { + dyn_get_modrm(); + if (GCC_UNLIKELY(decode.modrm.reg==DRC_SEG_CS)) IllegalOptionDynrec("dyn_mov_seg_ev"); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_RETOP,false); + } else { + gen_mov_word_to_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + } + gen_call_function_IR((void *)&CPU_SetSegGeneral,decode.modrm.reg,FC_RETOP); + if (cpu.pmode) dyn_check_exception(FC_RETOP); +} + +static void dyn_load_seg_off_ea(Bit8u seg) { + 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); + gen_protect_reg(FC_OP1); + + gen_restore_addr_reg(); + gen_add_imm(FC_ADDR,decode.big_op ? 4:2); + dyn_read_word(FC_ADDR,FC_RETOP,false); + + gen_call_function_IR((void *)&CPU_SetSegGeneral,seg,FC_RETOP); + if (cpu.pmode) dyn_check_exception(FC_RETOP); + + gen_restore_reg(FC_OP1); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + } else { + IllegalOptionDynrec("dyn_load_seg_off_ea"); + } +} + + + +static void dyn_imul_gvev(Bitu immsize) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + + switch (immsize) { + case 0: + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + break; + case 1: + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit8s)decode_fetchb()); + break; + case 2: + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit16s)decode_fetchw()); + break; + case 4: + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32s)decode_fetchd()); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)((Bit32s)decode_fetchd())); + break; + } + + if (decode.big_op) gen_call_function_raw((void*)dynrec_dimul_dword); + else gen_call_function_raw((void*)dynrec_dimul_word); + + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); +} + +static void dyn_dshift_ev_gv(bool left,bool immediate) { + 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); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + gen_mov_word_to_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + if (immediate) gen_mov_byte_to_reg_low_imm(FC_RETOP,decode_fetchb()); + else gen_mov_byte_to_reg_low(FC_RETOP,DRCD_REG_BYTE(DRC_REG_ECX,0)); + if (decode.big_op) dyn_dpshift_dword_gencall(left); + else dyn_dpshift_word_gencall(left); + + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } else { + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + + +static void dyn_grp1_eb_ib(void) { + dyn_get_modrm(); + DualOps op=grp1_table[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_byte_canuseword(FC_ADDR,FC_OP1); + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); + dyn_dop_byte_gencall(op); + + if ((op!=DOP_CMP) && (op!=DOP_TEST)) { + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_RETOP); + } + } else { + dyn_dop_byte_imm_mem(op,decode.modrm.rm&3,(decode.modrm.rm>>2)&1); + } +} + +static void dyn_grp1_ev_iv(bool withbyte) { + dyn_get_modrm(); + DualOps op=grp1_table[decode.modrm.reg]; + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + + if (!withbyte) { + dyn_prep_word_imm(FC_OP2); + } else { + Bits imm=(Bit8s)decode_fetchb(); + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,(Bit32u)imm); + else gen_mov_word_to_reg_imm(FC_OP2,(Bit16u)imm); + } + + dyn_dop_word_gencall(op,decode.big_op); + + if ((op!=DOP_CMP) && (op!=DOP_TEST)) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } + } else { + if (!withbyte) { + dyn_dop_word_imm(op,decode.modrm.rm); + } else { + Bits imm=withbyte ? (Bit8s)decode_fetchb() : (decode.big_op ? decode_fetchd(): decode_fetchw()); + dyn_dop_word_imm_old(op,decode.modrm.rm,imm); + } + } +} + + +static void dyn_grp2_eb(grp2_types type) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_byte_canuseword(FC_ADDR,FC_OP1); + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } + switch (type) { + case grp2_1: + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); + dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); + break; + case grp2_imm: { + Bit8u imm=decode_fetchb(); + if (imm) { + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); + dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); + } else return; + } + break; + case grp2_cl: + gen_mov_byte_to_reg_low_canuseword(FC_OP2,DRCD_REG_BYTE(DRC_REG_ECX,0)); + gen_and_imm(FC_OP2,0x1f); + dyn_shift_byte_gencall((ShiftOps)decode.modrm.reg); + break; + } + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_RETOP); + } else { + gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_grp2_ev(grp2_types type) { + 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); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + switch (type) { + case grp2_1: + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,1); + dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); + break; + case grp2_imm: { + Bitu val; + if (decode_fetchb_imm(val)) { + gen_mov_byte_to_reg_low_canuseword(FC_OP2,(void*)val); + gen_and_imm(FC_OP2,0x1f); + dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); + break; + } + Bit8u imm=(Bit8u)val; + if (imm) { + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,imm&0x1f); + dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); + } else return; + } + break; + case grp2_cl: + gen_mov_byte_to_reg_low_canuseword(FC_OP2,DRCD_REG_BYTE(DRC_REG_ECX,0)); + gen_and_imm(FC_OP2,0x1f); + dyn_shift_word_gencall((ShiftOps)decode.modrm.reg,decode.big_op); + break; + } + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } else { + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + + +static void dyn_grp3_eb(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); + dyn_read_byte_canuseword(FC_ADDR,FC_OP1); + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } + switch (decode.modrm.reg) { + case 0x0: // test eb,ib + gen_mov_byte_to_reg_low_imm_canuseword(FC_OP2,decode_fetchb()); + dyn_dop_byte_gencall(DOP_TEST); + return; + case 0x2: // NOT Eb + dyn_sop_byte_gencall(SOP_NOT); + break; + case 0x3: // NEG Eb + dyn_sop_byte_gencall(SOP_NEG); + break; + case 0x4: // mul Eb + gen_call_function_raw((void*)&dynrec_mul_byte); + return; + case 0x5: // imul Eb + gen_call_function_raw((void*)&dynrec_imul_byte); + return; + case 0x6: // div Eb + gen_call_function_raw((void*)&dynrec_div_byte); + dyn_check_exception(FC_RETOP); + return; + case 0x7: // idiv Eb + gen_call_function_raw((void*)&dynrec_idiv_byte); + dyn_check_exception(FC_RETOP); + return; + } + // Save the result if memory op + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_RETOP); + } else { + gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} + +static void dyn_grp3_ev(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + if ((decode.modrm.reg==2) || (decode.modrm.reg==3)) gen_protect_addr_reg(); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + switch (decode.modrm.reg) { + case 0x0: // test ev,iv + if (decode.big_op) gen_mov_dword_to_reg_imm(FC_OP2,decode_fetchd()); + else gen_mov_word_to_reg_imm(FC_OP2,decode_fetchw()); + dyn_dop_word_gencall(DOP_TEST,decode.big_op); + return; + case 0x2: // NOT Ev + dyn_sop_word_gencall(SOP_NOT,decode.big_op); + break; + case 0x3: // NEG Eb + dyn_sop_word_gencall(SOP_NEG,decode.big_op); + break; + case 0x4: // mul Eb + if (decode.big_op) gen_call_function_raw((void*)&dynrec_mul_dword); + else gen_call_function_raw((void*)&dynrec_mul_word); + return; + case 0x5: // imul Eb + if (decode.big_op) gen_call_function_raw((void*)&dynrec_imul_dword); + else gen_call_function_raw((void*)&dynrec_imul_word); + return; + case 0x6: // div Eb + if (decode.big_op) gen_call_function_raw((void*)&dynrec_div_dword); + else gen_call_function_raw((void*)&dynrec_div_word); + dyn_check_exception(FC_RETOP); + return; + case 0x7: // idiv Eb + if (decode.big_op) gen_call_function_raw((void*)&dynrec_idiv_dword); + else gen_call_function_raw((void*)&dynrec_idiv_word); + dyn_check_exception(FC_RETOP); + return; + } + // Save the result if memory op + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } else { + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } +} + + +static bool dyn_grp4_eb(void) { + dyn_get_modrm(); + switch (decode.modrm.reg) { + case 0x0://INC Eb + case 0x1://DEC Eb + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_byte_canuseword(FC_ADDR,FC_OP1); + dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); + gen_restore_addr_reg(); + dyn_write_byte(FC_ADDR,FC_RETOP); + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + dyn_sop_byte_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC); + gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } + break; + case 0x7: //CALBACK Iw + gen_mov_direct_dword(&core_dynrec.callback,decode_fetchw()); + dyn_set_eip_end(); + dyn_reduce_cycles(); + dyn_return(BR_CallBack); + dyn_closeblock(); + return true; + default: + IllegalOptionDynrec("dyn_grp4_eb"); + break; + } + return false; +} + +static bool dyn_grp4_ev(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + if ((decode.modrm.reg<2) || (decode.modrm.reg==3) || (decode.modrm.reg==5)) gen_protect_addr_reg(); + dyn_read_word(FC_ADDR,FC_OP1,decode.big_op); + } else { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + switch (decode.modrm.reg) { + case 0x0://INC Ev + case 0x1://DEC Ev + dyn_sop_word_gencall(decode.modrm.reg==0 ? SOP_INC : SOP_DEC,decode.big_op); + if (decode.modrm.mod<3) { + gen_restore_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,decode.big_op); + } else { + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,decode.big_op),decode.big_op); + } + break; + case 0x2: // CALL Ev + gen_mov_regs(FC_ADDR,FC_OP1); + gen_protect_addr_reg(); + gen_mov_word_to_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); + gen_add_imm(FC_OP1,(Bit32u)(decode.code-decode.code_start)); + if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); + else gen_call_function_raw((void*)&dynrec_push_word); + + gen_restore_addr_reg(); + gen_mov_word_from_reg(FC_ADDR,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); + return true; + case 0x4: // JMP Ev + gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); + return true; + case 0x3: // CALL Ep + case 0x5: // JMP Ep + if (!decode.big_op) gen_extend_word(false,FC_OP1); + if (decode.modrm.mod<3) gen_restore_addr_reg(); + gen_protect_reg(FC_OP1); + gen_add_imm(FC_ADDR,decode.big_op?4:2); + dyn_read_word(FC_ADDR,FC_OP2,decode.big_op); + gen_extend_word(false,FC_OP2); + + dyn_set_eip_last_end(FC_RETOP); + gen_restore_reg(FC_OP1,FC_ADDR); + gen_call_function_IRRR(decode.modrm.reg == 3 ? (void*)(&CPU_CALL) : (void*)(&CPU_JMP), + decode.big_op,FC_OP2,FC_ADDR,FC_RETOP); + return true; + case 0x6: // PUSH Ev + if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); + else gen_call_function_raw((void*)&dynrec_push_word); + break; + default: + IllegalOptionDynrec("dyn_grp4_ev"); + } + return false; +} + + +static bool dyn_grp6(void) { + dyn_get_modrm(); + switch (decode.modrm.reg) { + case 0x00: // SLDT + case 0x01: // STR + if (decode.modrm.reg==0) gen_call_function_raw((void*)CPU_SLDT); + else gen_call_function_raw((void*)CPU_STR); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_write_word(FC_ADDR,FC_RETOP,false); + } else { + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + } + break; + case 0x02: // LLDT + case 0x03: // LTR + case 0x04: // VERR + case 0x05: // VERW + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_RETOP,false); + } else { + gen_mov_word_to_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + } + gen_extend_word(false,FC_RETOP); + switch (decode.modrm.reg) { + case 0x02: // LLDT +// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); + if (cpu.cpl) E_Exit("lldt cpl>0"); + gen_call_function_R((void*)CPU_LLDT,FC_RETOP); + dyn_check_exception(FC_RETOP); + break; + case 0x03: // LTR +// if (cpu.cpl) return CPU_PrepareException(EXCEPTION_GP,0); + if (cpu.cpl) E_Exit("ltr cpl>0"); + gen_call_function_R((void*)CPU_LTR,FC_RETOP); + dyn_check_exception(FC_RETOP); + break; + case 0x04: // VERR + gen_call_function_R((void*)CPU_VERR,FC_RETOP); + break; + case 0x05: // VERW + gen_call_function_R((void*)CPU_VERW,FC_RETOP); + break; + } + break; + default: IllegalOptionDynrec("dyn_grp6"); + } + return false; +} + +static bool dyn_grp7(void) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + switch (decode.modrm.reg) { + case 0x00: // SGDT + gen_call_function_raw((void*)CPU_SGDT_limit); + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,false); + gen_call_function_raw((void*)CPU_SGDT_base); + gen_restore_addr_reg(); + gen_add_imm(FC_ADDR,2); + dyn_write_word(FC_ADDR,FC_RETOP,true); + break; + case 0x01: // SIDT + gen_call_function_raw((void*)CPU_SIDT_limit); + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_write_word(FC_ADDR,FC_RETOP,false); + gen_call_function_raw((void*)CPU_SIDT_base); + gen_restore_addr_reg(); + gen_add_imm(FC_ADDR,2); + dyn_write_word(FC_ADDR,FC_RETOP,true); + break; + case 0x02: // LGDT + case 0x03: // LIDT +// if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); + if (cpu.pmode && cpu.cpl) IllegalOptionDynrec("lgdt nonpriviledged"); + dyn_fill_ea(FC_ADDR); + gen_protect_addr_reg(); + dyn_read_word(FC_ADDR,FC_OP1,false); + gen_extend_word(false,FC_OP1); + gen_protect_reg(FC_OP1); + + gen_restore_addr_reg(); + gen_add_imm(FC_ADDR,2); + dyn_read_word(FC_ADDR,FC_OP2,true); + if (!decode.big_op) gen_and_imm(FC_OP2,0xffffff); + + gen_restore_reg(FC_OP1); + if (decode.modrm.reg==2) gen_call_function_RR((void*)CPU_LGDT,FC_OP1,FC_OP2); + else gen_call_function_RR((void*)CPU_LIDT,FC_OP1,FC_OP2); + break; + case 0x04: // SMSW + gen_call_function_raw((void*)CPU_SMSW); + dyn_fill_ea(FC_ADDR); + dyn_write_word(FC_ADDR,FC_RETOP,false); + break; + case 0x06: // LMSW + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_RETOP,false); + gen_call_function_R((void*)CPU_LMSW,FC_RETOP); + dyn_check_exception(FC_RETOP); + dyn_set_eip_end(); + dyn_reduce_cycles(); + dyn_return(BR_Normal); + dyn_closeblock(); + return true; + default: IllegalOptionDynrec("dyn_grp7_1"); + } + } else { + switch (decode.modrm.reg) { + case 0x04: // SMSW + gen_call_function_raw((void*)CPU_SMSW); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + break; + case 0x06: // LMSW + gen_mov_word_to_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + gen_call_function_R((void*)CPU_LMSW,FC_RETOP); + dyn_check_exception(FC_RETOP); + dyn_set_eip_end(); + dyn_reduce_cycles(); + dyn_return(BR_Normal); + dyn_closeblock(); + return true; + default: IllegalOptionDynrec("dyn_grp7_2"); + } + } + return false; +} + + +/* +static void dyn_larlsl(bool is_lar) { + dyn_get_modrm(); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_read_word(FC_ADDR,FC_RETOP,false); + } else { + gen_mov_word_to_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,false),false); + } + gen_extend_word(false,FC_RETOP); + if (is_lar) gen_call_function((void*)CPU_LAR,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); + else gen_call_function((void*)CPU_LSL,"%R%A",FC_RETOP,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); + DRC_PTR_SIZE_IM brnz=gen_create_branch_on_nonzero(FC_RETOP,true); + gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); + gen_mov_word_from_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.reg,decode.big_op),decode.big_op); + gen_fill_branch(brnz); +} +*/ + + +static void dyn_mov_from_crx(void) { + dyn_get_modrm(); + gen_call_function_IA((void*)CPU_READ_CRX,decode.modrm.reg,(DRC_PTR_SIZE_IM)&core_dynrec.readdata); + dyn_check_exception(FC_RETOP); + gen_mov_word_to_reg(FC_OP2,&core_dynrec.readdata,true); + gen_mov_word_from_reg(FC_OP2,DRCD_REG_WORD(decode.modrm.rm,true),true); +} + +static void dyn_mov_to_crx(void) { + dyn_get_modrm(); + gen_mov_word_to_reg(FC_RETOP,DRCD_REG_WORD(decode.modrm.rm,true),true); + gen_call_function_IR((void*)CPU_WRITE_CRX,decode.modrm.reg,FC_RETOP); + dyn_check_exception(FC_RETOP); + dyn_set_eip_end(); + dyn_reduce_cycles(); + dyn_return(BR_Normal); + dyn_closeblock(); +} + + +static void dyn_cbw(void) { + if (decode.big_op) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,false),false); + gen_call_function_raw((void *)&dynrec_cwde); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(DRC_REG_EAX,true),true); + } else { + gen_mov_byte_to_reg_low_canuseword(FC_OP1,DRCD_REG_BYTE(DRC_REG_EAX,0)); + gen_call_function_raw((void *)&dynrec_cbw); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(DRC_REG_EAX,false),false); + } +} + +static void dyn_cwd(void) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,decode.big_op),decode.big_op); + if (decode.big_op) { + gen_call_function_raw((void *)&dynrec_cdq); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(DRC_REG_EDX,true),true); + } else { + gen_call_function_raw((void *)&dynrec_cwd); + gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(DRC_REG_EDX,false),false); + } +} + +static void dyn_sahf(void) { + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,false),false); + gen_call_function_raw((void *)&dynrec_sahf); + InvalidateFlags(); +} + + +static void dyn_exit_link(Bits eip_change) { + gen_add_direct_word(®_eip,(decode.code-decode.code_start)+eip_change,decode.big_op); + dyn_reduce_cycles(); + gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); + dyn_closeblock(); +} + + +static void dyn_branched_exit(BranchTypes btype,Bit32s eip_add) { + Bitu eip_base=decode.code-decode.code_start; + dyn_reduce_cycles(); + + dyn_branchflag_to_reg(btype); + DRC_PTR_SIZE_IM data=gen_create_branch_on_nonzero(FC_RETOP,true); + + // Branch not taken + gen_add_direct_word(®_eip,eip_base,decode.big_op); + gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); + gen_fill_branch(data); + + // Branch taken + gen_add_direct_word(®_eip,eip_base+eip_add,decode.big_op); + gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); + dyn_closeblock(); +} + +/* +static void dyn_set_byte_on_condition(BranchTypes btype) { + dyn_get_modrm(); + dyn_branchflag_to_reg(btype); + gen_and_imm(FC_RETOP,1); + if (decode.modrm.mod<3) { + dyn_fill_ea(FC_ADDR); + dyn_write_byte(FC_ADDR,FC_RETOP); + } else { + gen_mov_byte_from_reg_low(FC_RETOP,DRCD_REG_BYTE(decode.modrm.rm&3,(decode.modrm.rm>>2)&1)); + } +} +*/ + +static void dyn_loop(LoopTypes type) { + dyn_reduce_cycles(); + Bits eip_add=(Bit8s)decode_fetchb(); + Bitu eip_base=decode.code-decode.code_start; + DRC_PTR_SIZE_IM branch1=0; + DRC_PTR_SIZE_IM branch2=0; + switch (type) { + case LOOP_E: + dyn_branchflag_to_reg(BR_NZ); + branch1=gen_create_branch_on_nonzero(FC_RETOP,true); + break; + case LOOP_NE: + dyn_branchflag_to_reg(BR_Z); + branch1=gen_create_branch_on_nonzero(FC_RETOP,true); + break; + } + switch (type) { + case LOOP_E: + case LOOP_NE: + case LOOP_NONE: + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + gen_add_imm(FC_OP1,(Bit32u)(-1)); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + branch2=gen_create_branch_on_zero(FC_OP1,decode.big_addr); + break; + case LOOP_JCXZ: + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + branch2=gen_create_branch_on_nonzero(FC_OP1,decode.big_addr); + break; + } + gen_add_direct_word(®_eip,eip_base+eip_add,true); + gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); + if (branch1) { + gen_fill_branch(branch1); + gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + gen_add_imm(FC_OP1,(Bit32u)(-1)); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + } + // Branch taken + gen_fill_branch(branch2); + gen_add_direct_word(®_eip,eip_base,decode.big_op); + gen_jmp_ptr(&decode.block->link[1].to,offsetof(CacheBlockDynRec,cache.start)); + dyn_closeblock(); +} + + +static void dyn_ret_near(Bitu bytes) { + dyn_reduce_cycles(); + + if (decode.big_op) gen_call_function_raw((void*)&dynrec_pop_dword); + else { + gen_call_function_raw((void*)&dynrec_pop_word); + gen_extend_word(false,FC_RETOP); + } + gen_mov_word_from_reg(FC_RETOP,decode.big_op?(void*)(®_eip):(void*)(®_ip),true); + + if (bytes) gen_add_direct_word(®_esp,bytes,true); + dyn_return(BR_Normal); + dyn_closeblock(); +} + +static void dyn_call_near_imm(void) { + Bits imm; + if (decode.big_op) imm=(Bit32s)decode_fetchd(); + else imm=(Bit16s)decode_fetchw(); + dyn_set_eip_end(FC_OP1); + if (decode.big_op) gen_call_function_raw((void*)&dynrec_push_dword); + else gen_call_function_raw((void*)&dynrec_push_word); + + dyn_set_eip_end(FC_OP1,imm); + gen_mov_word_from_reg(FC_OP1,decode.big_op?(void*)(®_eip):(void*)(®_ip),decode.big_op); + + dyn_reduce_cycles(); + gen_jmp_ptr(&decode.block->link[0].to,offsetof(CacheBlockDynRec,cache.start)); + dyn_closeblock(); +} + +static void dyn_ret_far(Bitu bytes) { + dyn_reduce_cycles(); + dyn_set_eip_last_end(FC_RETOP); + gen_call_function_IIR((void*)&CPU_RET,decode.big_op,bytes,FC_RETOP); + dyn_return(BR_Normal); + dyn_closeblock(); +} + +static void dyn_call_far_imm(void) { + Bitu sel,off; + off=decode.big_op ? decode_fetchd() : decode_fetchw(); + sel=decode_fetchw(); + dyn_reduce_cycles(); + dyn_set_eip_last_end(FC_RETOP); + gen_call_function_IIIR((void*)&CPU_CALL,decode.big_op,sel,off,FC_RETOP); + dyn_return(BR_Normal); + dyn_closeblock(); +} + +static void dyn_jmp_far_imm(void) { + Bitu sel,off; + off=decode.big_op ? decode_fetchd() : decode_fetchw(); + sel=decode_fetchw(); + dyn_reduce_cycles(); + dyn_set_eip_last_end(FC_RETOP); + gen_call_function_IIIR((void*)&CPU_JMP,decode.big_op,sel,off,FC_RETOP); + dyn_return(BR_Normal); + dyn_closeblock(); +} + +static void dyn_iret(void) { + dyn_reduce_cycles(); + dyn_set_eip_last_end(FC_RETOP); + gen_call_function_IR((void*)&CPU_IRET,decode.big_op,FC_RETOP); + dyn_return(BR_Iret); + dyn_closeblock(); +} + +static void dyn_interrupt(Bit8u num) { + dyn_reduce_cycles(); + dyn_set_eip_last_end(FC_RETOP); + gen_call_function_IIR((void*)&CPU_Interrupt,num,CPU_INT_SOFTWARE,FC_RETOP); + dyn_return(BR_Normal); + dyn_closeblock(); +} + + + +static void dyn_string(StringOps op) { + if (decode.rep) gen_mov_word_to_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + else gen_mov_dword_to_reg_imm(FC_OP1,1); + gen_mov_word_to_reg(FC_OP2,&cpu.direction,true); + Bit8u di_base_addr=decode.seg_prefix_used ? decode.seg_prefix : DRC_SEG_DS; + switch (op) { + case STR_MOVSB: + if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_mm((void*)&dynrec_movsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + case STR_MOVSW: + if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_mm((void*)&dynrec_movsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + case STR_MOVSD: + if (decode.big_addr) gen_call_function_mm((void*)&dynrec_movsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_mm((void*)&dynrec_movsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr),(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + + case STR_LODSB: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsb_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + else gen_call_function_m((void*)&dynrec_lodsb_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + break; + case STR_LODSW: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsw_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + else gen_call_function_m((void*)&dynrec_lodsw_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + break; + case STR_LODSD: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_lodsd_dword,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + else gen_call_function_m((void*)&dynrec_lodsd_word,(Bitu)DRCD_SEG_PHYS(di_base_addr)); + break; + + case STR_STOSB: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosb_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_m((void*)&dynrec_stosb_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + case STR_STOSW: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosw_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_m((void*)&dynrec_stosw_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + case STR_STOSD: + if (decode.big_addr) gen_call_function_m((void*)&dynrec_stosd_dword,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + else gen_call_function_m((void*)&dynrec_stosd_word,(Bitu)DRCD_SEG_PHYS(DRC_SEG_ES)); + break; + default: IllegalOptionDynrec("dyn_string"); + } + if (decode.rep) gen_mov_word_from_reg(FC_RETOP,DRCD_REG_WORD(DRC_REG_ECX,decode.big_addr),decode.big_addr); + + if (op +#include +#include "cross.h" +#include "mem.h" +#include "fpu.h" +#include "cpu.h" + + +static void FPU_FDECSTP(){ + TOP = (TOP - 1) & 7; +} + +static void FPU_FINCSTP(){ + TOP = (TOP + 1) & 7; +} + +static void FPU_FNSTCW(PhysPt addr){ + mem_writew(addr,fpu.cw); +} + +static void FPU_FFREE(Bitu st) { + fpu.tags[st]=TAG_Empty; +} + + +#if C_FPU_X86 +#include "../../fpu/fpu_instructions_x86.h" +#else +#include "../../fpu/fpu_instructions.h" +#endif + + +static INLINE void dyn_fpu_top() { + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_add_imm(FC_OP2,decode.modrm.rm); + gen_and_imm(FC_OP2,7); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); +} + +static INLINE void dyn_fpu_top_swapped() { + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_add_imm(FC_OP1,decode.modrm.rm); + gen_and_imm(FC_OP1,7); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); +} + +static void dyn_eatree() { + Bitu group=(decode.modrm.val >> 3) & 7; + switch (group){ + case 0x00: // FADD ST,STi + gen_call_function_R((void*)&FPU_FADD_EA,FC_OP1); + break; + case 0x01: // FMUL ST,STi + gen_call_function_R((void*)&FPU_FMUL_EA,FC_OP1); + break; + case 0x02: // FCOM STi + gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); + break; + case 0x03: // FCOMP STi + gen_call_function_R((void*)&FPU_FCOM_EA,FC_OP1); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: // FSUB ST,STi + gen_call_function_R((void*)&FPU_FSUB_EA,FC_OP1); + break; + case 0x05: // FSUBR ST,STi + gen_call_function_R((void*)&FPU_FSUBR_EA,FC_OP1); + break; + case 0x06: // FDIV ST,STi + gen_call_function_R((void*)&FPU_FDIV_EA,FC_OP1); + break; + case 0x07: // FDIVR ST,STi + gen_call_function_R((void*)&FPU_FDIVR_EA,FC_OP1); + break; + default: + break; + } +} + +static void dyn_fpu_esc0(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + dyn_fpu_top(); + switch (decode.modrm.reg){ + case 0x00: //FADD ST,STi + gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); + break; + case 0x01: // FMUL ST,STi + gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); + break; + case 0x02: // FCOM STi + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + break; + case 0x03: // FCOMP STi + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: // FSUB ST,STi + gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); + break; + case 0x05: // FSUBR ST,STi + gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); + break; + case 0x06: // FDIV ST,STi + gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); + break; + case 0x07: // FDIVR ST,STi + gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); + break; + default: + break; + } + } else { + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLD_F32_EA,FC_ADDR); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + dyn_eatree(); + } +} + + +static void dyn_fpu_esc1(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch (decode.modrm.reg){ + case 0x00: /* FLD STi */ + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_add_imm(FC_OP1,decode.modrm.rm); + gen_and_imm(FC_OP1,7); + gen_protect_reg(FC_OP1); + gen_call_function_raw((void*)&FPU_PREP_PUSH); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_restore_reg(FC_OP1); + gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); + break; + case 0x01: /* FXCH STi */ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); + break; + case 0x02: /* FNOP */ + gen_call_function_raw((void*)&FPU_FNOP); + break; + case 0x03: /* FSTP STi */ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: + switch(decode.modrm.rm){ + case 0x00: /* FCHS */ + gen_call_function_raw((void*)&FPU_FCHS); + break; + case 0x01: /* FABS */ + gen_call_function_raw((void*)&FPU_FABS); + break; + case 0x02: /* UNKNOWN */ + case 0x03: /* ILLEGAL */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + case 0x04: /* FTST */ + gen_call_function_raw((void*)&FPU_FTST); + break; + case 0x05: /* FXAM */ + gen_call_function_raw((void*)&FPU_FXAM); + break; + case 0x06: /* FTSTP (cyrix)*/ + case 0x07: /* UNKNOWN */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + case 0x05: + switch(decode.modrm.rm){ + case 0x00: /* FLD1 */ + gen_call_function_raw((void*)&FPU_FLD1); + break; + case 0x01: /* FLDL2T */ + gen_call_function_raw((void*)&FPU_FLDL2T); + break; + case 0x02: /* FLDL2E */ + gen_call_function_raw((void*)&FPU_FLDL2E); + break; + case 0x03: /* FLDPI */ + gen_call_function_raw((void*)&FPU_FLDPI); + break; + case 0x04: /* FLDLG2 */ + gen_call_function_raw((void*)&FPU_FLDLG2); + break; + case 0x05: /* FLDLN2 */ + gen_call_function_raw((void*)&FPU_FLDLN2); + break; + case 0x06: /* FLDZ*/ + gen_call_function_raw((void*)&FPU_FLDZ); + break; + case 0x07: /* ILLEGAL */ + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + case 0x06: + switch(decode.modrm.rm){ + case 0x00: /* F2XM1 */ + gen_call_function_raw((void*)&FPU_F2XM1); + break; + case 0x01: /* FYL2X */ + gen_call_function_raw((void*)&FPU_FYL2X); + break; + case 0x02: /* FPTAN */ + gen_call_function_raw((void*)&FPU_FPTAN); + break; + case 0x03: /* FPATAN */ + gen_call_function_raw((void*)&FPU_FPATAN); + break; + case 0x04: /* FXTRACT */ + gen_call_function_raw((void*)&FPU_FXTRACT); + break; + case 0x05: /* FPREM1 */ + gen_call_function_raw((void*)&FPU_FPREM1); + break; + case 0x06: /* FDECSTP */ + gen_call_function_raw((void*)&FPU_FDECSTP); + break; + case 0x07: /* FINCSTP */ + gen_call_function_raw((void*)&FPU_FINCSTP); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + case 0x07: + switch(decode.modrm.rm){ + case 0x00: /* FPREM */ + gen_call_function_raw((void*)&FPU_FPREM); + break; + case 0x01: /* FYL2XP1 */ + gen_call_function_raw((void*)&FPU_FYL2XP1); + break; + case 0x02: /* FSQRT */ + gen_call_function_raw((void*)&FPU_FSQRT); + break; + case 0x03: /* FSINCOS */ + gen_call_function_raw((void*)&FPU_FSINCOS); + break; + case 0x04: /* FRNDINT */ + gen_call_function_raw((void*)&FPU_FRNDINT); + break; + case 0x05: /* FSCALE */ + gen_call_function_raw((void*)&FPU_FSCALE); + break; + case 0x06: /* FSIN */ + gen_call_function_raw((void*)&FPU_FSIN); + break; + case 0x07: /* FCOS */ + gen_call_function_raw((void*)&FPU_FCOS); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 1:Unhandled group %X subfunction %X",decode.modrm.reg,decode.modrm.rm); + break; + } + } else { + switch(decode.modrm.reg){ + case 0x00: /* FLD float*/ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + dyn_fill_ea(FC_OP1); + gen_call_function_RR((void*)&FPU_FLD_F32,FC_OP1,FC_OP2); + break; + case 0x01: /* UNKNOWN */ + LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + case 0x02: /* FST float*/ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); + break; + case 0x03: /* FSTP float*/ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_F32,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: /* FLDENV */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLDENV,FC_ADDR); + break; + case 0x05: /* FLDCW */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void *)&FPU_FLDCW,FC_ADDR); + break; + case 0x06: /* FSTENV */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void *)&FPU_FSTENV,FC_ADDR); + break; + case 0x07: /* FNSTCW*/ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void *)&FPU_FNSTCW,FC_ADDR); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC EA 1:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } +} + +static void dyn_fpu_esc2(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch(decode.modrm.reg){ + case 0x05: + switch(decode.modrm.rm){ + case 0x01: /* FUCOMPP */ + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_add_imm(FC_OP2,1); + gen_and_imm(FC_OP2,7); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_call_function_RR((void *)&FPU_FUCOM,FC_OP1,FC_OP2); + gen_call_function_raw((void *)&FPU_FPOP); + gen_call_function_raw((void *)&FPU_FPOP); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 2:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } else { + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLD_I32_EA,FC_ADDR); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + dyn_eatree(); + } +} + +static void dyn_fpu_esc3(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch (decode.modrm.reg) { + case 0x04: + switch (decode.modrm.rm) { + case 0x00: //FNENI + case 0x01: //FNDIS + LOG(LOG_FPU,LOG_ERROR)("8087 only fpu code used esc 3: group 4: subfuntion: %d",decode.modrm.rm); + break; + case 0x02: //FNCLEX FCLEX + gen_call_function_raw((void*)&FPU_FCLEX); + break; + case 0x03: //FNINIT FINIT + gen_call_function_raw((void*)&FPU_FINIT); + break; + case 0x04: //FNSETPM + case 0x05: //FRSTPM +// LOG(LOG_FPU,LOG_ERROR)("80267 protected mode (un)set. Nothing done"); + break; + default: + E_Exit("ESC 3:ILLEGAL OPCODE group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 3:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } else { + switch(decode.modrm.reg){ + case 0x00: /* FILD */ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + dyn_fill_ea(FC_OP1); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_call_function_RR((void*)&FPU_FLD_I32,FC_OP1,FC_OP2); + break; + case 0x01: /* FISTTP */ + LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + case 0x02: /* FIST */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); + break; + case 0x03: /* FISTP */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_I32,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x05: /* FLD 80 Bits Real */ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLD_F80,FC_ADDR); + break; + case 0x07: /* FSTP 80 Bits Real */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_F80,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 3 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + } + } +} + +static void dyn_fpu_esc4(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch(decode.modrm.reg){ + case 0x00: /* FADD STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); + break; + case 0x01: /* FMUL STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); + break; + case 0x02: /* FCOM*/ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + break; + case 0x03: /* FCOMP*/ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: /* FSUBR STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); + break; + case 0x05: /* FSUB STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); + break; + case 0x06: /* FDIVR STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); + break; + case 0x07: /* FDIV STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); + break; + default: + break; + } + } else { + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLD_F64_EA,FC_ADDR); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + dyn_eatree(); + } +} + +static void dyn_fpu_esc5(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + dyn_fpu_top(); + switch(decode.modrm.reg){ + case 0x00: /* FFREE STi */ + gen_call_function_R((void*)&FPU_FFREE,FC_OP2); + break; + case 0x01: /* FXCH STi*/ + gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); + break; + case 0x02: /* FST STi */ + gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); + break; + case 0x03: /* FSTP STi*/ + gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: /* FUCOM STi */ + gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); + break; + case 0x05: /*FUCOMP STi */ + gen_call_function_RR((void*)&FPU_FUCOM,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 5:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } else { + switch(decode.modrm.reg){ + case 0x00: /* FLD double real*/ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + dyn_fill_ea(FC_OP1); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_call_function_RR((void*)&FPU_FLD_F64,FC_OP1,FC_OP2); + break; + case 0x01: /* FISTTP longint*/ + LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + case 0x02: /* FST double real*/ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); + break; + case 0x03: /* FSTP double real*/ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_F64,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: /* FRSTOR */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FRSTOR,FC_ADDR); + break; + case 0x06: /* FSAVE */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FSAVE,FC_ADDR); + break; + case 0x07: /*FNSTSW */ + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); + gen_mov_word_to_reg(FC_OP2,(void*)(&fpu.sw),true); + dyn_fill_ea(FC_OP1); + gen_call_function_RR((void*)&mem_writew,FC_OP1,FC_OP2); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 5 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + } + } +} + +static void dyn_fpu_esc6(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch(decode.modrm.reg){ + case 0x00: /*FADDP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FADD,FC_OP1,FC_OP2); + break; + case 0x01: /* FMULP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FMUL,FC_OP1,FC_OP2); + break; + case 0x02: /* FCOMP5*/ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + break; /* TODO IS THIS ALLRIGHT ????????? */ + case 0x03: /*FCOMPP*/ + if(decode.modrm.rm != 1) { + LOG(LOG_FPU,LOG_WARN)("ESC 6:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + return; + } + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + gen_add_imm(FC_OP2,1); + gen_and_imm(FC_OP2,7); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_call_function_RR((void*)&FPU_FCOM,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); /* extra pop at the bottom*/ + break; + case 0x04: /* FSUBRP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FSUBR,FC_OP1,FC_OP2); + break; + case 0x05: /* FSUBP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FSUB,FC_OP1,FC_OP2); + break; + case 0x06: /* FDIVRP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FDIVR,FC_OP1,FC_OP2); + break; + case 0x07: /* FDIVP STi,ST*/ + dyn_fpu_top_swapped(); + gen_call_function_RR((void*)&FPU_FDIV,FC_OP1,FC_OP2); + break; + default: + break; + } + gen_call_function_raw((void*)&FPU_FPOP); + } else { + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FLD_I16_EA,FC_ADDR); + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + dyn_eatree(); + } +} + +static void dyn_fpu_esc7(){ + dyn_get_modrm(); + if (decode.modrm.val >= 0xc0) { + switch (decode.modrm.reg){ + case 0x01: /* FXCH STi*/ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FXCH,FC_OP1,FC_OP2); + break; + case 0x02: /* FSTP STi*/ + case 0x03: /* FSTP STi*/ + dyn_fpu_top(); + gen_call_function_RR((void*)&FPU_FST,FC_OP1,FC_OP2); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: + switch(decode.modrm.rm){ + case 0x00: /* FNSTSW AX*/ + gen_mov_word_to_reg(FC_OP1,(void*)(&TOP),true); + gen_call_function_R((void*)&FPU_SET_TOP,FC_OP1); + gen_mov_word_to_reg(FC_OP1,(void*)(&fpu.sw),false); + gen_mov_word_from_reg(FC_OP1,DRCD_REG_WORD(DRC_REG_EAX,false),false); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } else { + switch(decode.modrm.reg){ + case 0x00: /* FILD Bit16s */ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + dyn_fill_ea(FC_OP1); + gen_call_function_RR((void*)&FPU_FLD_I16,FC_OP1,FC_OP2); + break; + case 0x01: + LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + case 0x02: /* FIST Bit16s */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); + break; + case 0x03: /* FISTP Bit16s */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_I16,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x04: /* FBLD packed BCD */ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + dyn_fill_ea(FC_OP1); + gen_call_function_RR((void*)&FPU_FBLD,FC_OP1,FC_OP2); + break; + case 0x05: /* FILD Bit64s */ + gen_call_function_raw((void*)&FPU_PREP_PUSH); + gen_mov_word_to_reg(FC_OP2,(void*)(&TOP),true); + dyn_fill_ea(FC_OP1); + gen_call_function_RR((void*)&FPU_FLD_I64,FC_OP1,FC_OP2); + break; + case 0x06: /* FBSTP packed BCD */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FBST,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + case 0x07: /* FISTP Bit64s */ + dyn_fill_ea(FC_ADDR); + gen_call_function_R((void*)&FPU_FST_I64,FC_ADDR); + gen_call_function_raw((void*)&FPU_FPOP); + break; + default: + LOG(LOG_FPU,LOG_WARN)("ESC 7 EA:Unhandled group %d subfunction %d",decode.modrm.reg,decode.modrm.rm); + break; + } + } +} + +#endif diff --git a/src/cpu/core_dynrec/operators.h b/src/cpu/core_dynrec/operators.h new file mode 100644 index 0000000..65b3dbf --- /dev/null +++ b/src/cpu/core_dynrec/operators.h @@ -0,0 +1,1995 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_add_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=(Bit8u)(lf_var1b+lf_var2b); + lflags.type=t_ADDb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_add_byte_simple(Bit8u op1,Bit8u op2) { + return op1+op2; +} + +static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_adc_byte(Bit8u op1,Bit8u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1b=op1; + lf_var2b=op2; + lf_resb=(Bit8u)(lf_var1b+lf_var2b+lflags.oldcf); + lflags.type=t_ADCb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_adc_byte_simple(Bit8u op1,Bit8u op2) { + return (Bit8u)(op1+op2+(Bitu)(get_CF()!=0)); +} + +static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sub_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=(Bit8u)(lf_var1b-lf_var2b); + lflags.type=t_SUBb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sub_byte_simple(Bit8u op1,Bit8u op2) { + return op1-op2; +} + +static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sbb_byte(Bit8u op1,Bit8u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1b=op1; + lf_var2b=op2; + lf_resb=(Bit8u)(lf_var1b-(lf_var2b+lflags.oldcf)); + lflags.type=t_SBBb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sbb_byte_simple(Bit8u op1,Bit8u op2) { + return (Bit8u)(op1-(op2+(Bitu)(get_CF()!=0))); +} + +static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=(Bit8u)(lf_var1b-lf_var2b); + lflags.type=t_CMPb; +} + +static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_byte_simple(Bit8u op1,Bit8u op2) { +} + +static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_xor_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b ^ lf_var2b; + lflags.type=t_XORb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_xor_byte_simple(Bit8u op1,Bit8u op2) { + return op1 ^ op2; +} + +static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_and_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b & lf_var2b; + lflags.type=t_ANDb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_and_byte_simple(Bit8u op1,Bit8u op2) { + return op1 & op2; +} + +static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_or_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b | lf_var2b; + lflags.type=t_ORb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_or_byte_simple(Bit8u op1,Bit8u op2) { + return op1 | op2; +} + +static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_byte(Bit8u op1,Bit8u op2) { + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b & lf_var2b; + lflags.type=t_TESTb; +} + +static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_byte_simple(Bit8u op1,Bit8u op2) { +} + +static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_add_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=(Bit16u)(lf_var1w+lf_var2w); + lflags.type=t_ADDw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_add_word_simple(Bit16u op1,Bit16u op2) { + return op1+op2; +} + +static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_adc_word(Bit16u op1,Bit16u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1w=op1; + lf_var2w=op2; + lf_resw=(Bit16u)(lf_var1w+lf_var2w+lflags.oldcf); + lflags.type=t_ADCw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_adc_word_simple(Bit16u op1,Bit16u op2) { + return (Bit16u)(op1+op2+(Bitu)(get_CF()!=0)); +} + +static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sub_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=(Bit16u)(lf_var1w-lf_var2w); + lflags.type=t_SUBw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sub_word_simple(Bit16u op1,Bit16u op2) { + return op1-op2; +} + +static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sbb_word(Bit16u op1,Bit16u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1w=op1; + lf_var2w=op2; + lf_resw=(Bit16u)(lf_var1w-(lf_var2w+lflags.oldcf)); + lflags.type=t_SBBw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sbb_word_simple(Bit16u op1,Bit16u op2) { + return (Bit16u)(op1-(op2+(Bitu)(get_CF()!=0))); +} + +static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=(Bit16u)(lf_var1w-lf_var2w); + lflags.type=t_CMPw; +} + +static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_word_simple(Bit16u op1,Bit16u op2) { +} + +static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_xor_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=lf_var1w ^ lf_var2w; + lflags.type=t_XORw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_xor_word_simple(Bit16u op1,Bit16u op2) { + return op1 ^ op2; +} + +static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_and_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=lf_var1w & lf_var2w; + lflags.type=t_ANDw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_and_word_simple(Bit16u op1,Bit16u op2) { + return op1 & op2; +} + +static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_or_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=lf_var1w | lf_var2w; + lflags.type=t_ORw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_or_word_simple(Bit16u op1,Bit16u op2) { + return op1 | op2; +} + +static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_word(Bit16u op1,Bit16u op2) { + lf_var1w=op1; + lf_var2w=op2; + lf_resw=lf_var1w & lf_var2w; + lflags.type=t_TESTw; +} + +static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_word_simple(Bit16u op1,Bit16u op2) { +} + +static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_add_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d+lf_var2d; + lflags.type=t_ADDd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_add_dword_simple(Bit32u op1,Bit32u op2) { + return op1 + op2; +} + +static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_adc_dword(Bit32u op1,Bit32u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d+lf_var2d+lflags.oldcf; + lflags.type=t_ADCd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_adc_dword_simple(Bit32u op1,Bit32u op2) { + return op1+op2+(Bitu)(get_CF()!=0); +} + +static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sub_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d-lf_var2d; + lflags.type=t_SUBd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sub_dword_simple(Bit32u op1,Bit32u op2) { + return op1-op2; +} + +static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sbb_dword(Bit32u op1,Bit32u op2) { + lflags.oldcf=get_CF()!=0; + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d-(lf_var2d+lflags.oldcf); + lflags.type=t_SBBd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sbb_dword_simple(Bit32u op1,Bit32u op2) { + return op1-(op2+(Bitu)(get_CF()!=0)); +} + +static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d-lf_var2d; + lflags.type=t_CMPd; +} + +static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_cmp_dword_simple(Bit32u op1,Bit32u op2) { +} + +static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_xor_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d ^ lf_var2d; + lflags.type=t_XORd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_xor_dword_simple(Bit32u op1,Bit32u op2) { + return op1 ^ op2; +} + +static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_and_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d & lf_var2d; + lflags.type=t_ANDd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_and_dword_simple(Bit32u op1,Bit32u op2) { + return op1 & op2; +} + +static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_or_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d | lf_var2d; + lflags.type=t_ORd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_or_dword_simple(Bit32u op1,Bit32u op2) { + return op1 | op2; +} + +static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_dword(Bit32u op1,Bit32u op2) { + lf_var1d=op1; + lf_var2d=op2; + lf_resd=lf_var1d & lf_var2d; + lflags.type=t_TESTd; +} + +static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) DRC_FC; +static void DRC_CALL_CONV dynrec_test_dword_simple(Bit32u op1,Bit32u op2) { +} + + +static void dyn_dop_byte_gencall(DualOps op) { + switch (op) { + case DOP_ADD: + InvalidateFlags((void*)&dynrec_add_byte_simple,t_ADDb); + gen_call_function_raw((void*)&dynrec_add_byte); + break; + case DOP_ADC: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_adc_byte_simple,t_ADCb); + gen_call_function_raw((void*)&dynrec_adc_byte); + break; + case DOP_SUB: + InvalidateFlags((void*)&dynrec_sub_byte_simple,t_SUBb); + gen_call_function_raw((void*)&dynrec_sub_byte); + break; + case DOP_SBB: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_sbb_byte_simple,t_SBBb); + gen_call_function_raw((void*)&dynrec_sbb_byte); + break; + case DOP_CMP: + InvalidateFlags((void*)&dynrec_cmp_byte_simple,t_CMPb); + gen_call_function_raw((void*)&dynrec_cmp_byte); + break; + case DOP_XOR: + InvalidateFlags((void*)&dynrec_xor_byte_simple,t_XORb); + gen_call_function_raw((void*)&dynrec_xor_byte); + break; + case DOP_AND: + InvalidateFlags((void*)&dynrec_and_byte_simple,t_ANDb); + gen_call_function_raw((void*)&dynrec_and_byte); + break; + case DOP_OR: + InvalidateFlags((void*)&dynrec_or_byte_simple,t_ORb); + gen_call_function_raw((void*)&dynrec_or_byte); + break; + case DOP_TEST: + InvalidateFlags((void*)&dynrec_test_byte_simple,t_TESTb); + gen_call_function_raw((void*)&dynrec_test_byte); + break; + default: IllegalOptionDynrec("dyn_dop_byte_gencall"); + } +} + +static void dyn_dop_word_gencall(DualOps op,bool dword) { + if (dword) { + switch (op) { + case DOP_ADD: + InvalidateFlags((void*)&dynrec_add_dword_simple,t_ADDd); + gen_call_function_raw((void*)&dynrec_add_dword); + break; + case DOP_ADC: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_adc_dword_simple,t_ADCd); + gen_call_function_raw((void*)&dynrec_adc_dword); + break; + case DOP_SUB: + InvalidateFlags((void*)&dynrec_sub_dword_simple,t_SUBd); + gen_call_function_raw((void*)&dynrec_sub_dword); + break; + case DOP_SBB: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_sbb_dword_simple,t_SBBd); + gen_call_function_raw((void*)&dynrec_sbb_dword); + break; + case DOP_CMP: + InvalidateFlags((void*)&dynrec_cmp_dword_simple,t_CMPd); + gen_call_function_raw((void*)&dynrec_cmp_dword); + break; + case DOP_XOR: + InvalidateFlags((void*)&dynrec_xor_dword_simple,t_XORd); + gen_call_function_raw((void*)&dynrec_xor_dword); + break; + case DOP_AND: + InvalidateFlags((void*)&dynrec_and_dword_simple,t_ANDd); + gen_call_function_raw((void*)&dynrec_and_dword); + break; + case DOP_OR: + InvalidateFlags((void*)&dynrec_or_dword_simple,t_ORd); + gen_call_function_raw((void*)&dynrec_or_dword); + break; + case DOP_TEST: + InvalidateFlags((void*)&dynrec_test_dword_simple,t_TESTd); + gen_call_function_raw((void*)&dynrec_test_dword); + break; + default: IllegalOptionDynrec("dyn_dop_dword_gencall"); + } + } else { + switch (op) { + case DOP_ADD: + InvalidateFlags((void*)&dynrec_add_word_simple,t_ADDw); + gen_call_function_raw((void*)&dynrec_add_word); + break; + case DOP_ADC: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_adc_word_simple,t_ADCw); + gen_call_function_raw((void*)&dynrec_adc_word); + break; + case DOP_SUB: + InvalidateFlags((void*)&dynrec_sub_word_simple,t_SUBw); + gen_call_function_raw((void*)&dynrec_sub_word); + break; + case DOP_SBB: + AcquireFlags(FLAG_CF); + InvalidateFlagsPartially((void*)&dynrec_sbb_word_simple,t_SBBw); + gen_call_function_raw((void*)&dynrec_sbb_word); + break; + case DOP_CMP: + InvalidateFlags((void*)&dynrec_cmp_word_simple,t_CMPw); + gen_call_function_raw((void*)&dynrec_cmp_word); + break; + case DOP_XOR: + InvalidateFlags((void*)&dynrec_xor_word_simple,t_XORw); + gen_call_function_raw((void*)&dynrec_xor_word); + break; + case DOP_AND: + InvalidateFlags((void*)&dynrec_and_word_simple,t_ANDw); + gen_call_function_raw((void*)&dynrec_and_word); + break; + case DOP_OR: + InvalidateFlags((void*)&dynrec_or_word_simple,t_ORw); + gen_call_function_raw((void*)&dynrec_or_word); + break; + case DOP_TEST: + InvalidateFlags((void*)&dynrec_test_word_simple,t_TESTw); + gen_call_function_raw((void*)&dynrec_test_word); + break; + default: IllegalOptionDynrec("dyn_dop_word_gencall"); + } + } +} + + +static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_inc_byte(Bit8u op) { + LoadCF; + lf_var1b=op; + lf_resb=lf_var1b+1; + lflags.type=t_INCb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_inc_byte_simple(Bit8u op) { + return op+1; +} + +static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_dec_byte(Bit8u op) { + LoadCF; + lf_var1b=op; + lf_resb=lf_var1b-1; + lflags.type=t_DECb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_dec_byte_simple(Bit8u op) { + return op-1; +} + +static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_not_byte(Bit8u op) { + return ~op; +} + +static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_neg_byte(Bit8u op) { + lf_var1b=op; + lf_resb=0-lf_var1b; + lflags.type=t_NEGb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_neg_byte_simple(Bit8u op) { + return 0-op; +} + +static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_inc_word(Bit16u op) { + LoadCF; + lf_var1w=op; + lf_resw=lf_var1w+1; + lflags.type=t_INCw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_inc_word_simple(Bit16u op) { + return op+1; +} + +static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dec_word(Bit16u op) { + LoadCF; + lf_var1w=op; + lf_resw=lf_var1w-1; + lflags.type=t_DECw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dec_word_simple(Bit16u op) { + return op-1; +} + +static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_not_word(Bit16u op) { + return ~op; +} + +static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_neg_word(Bit16u op) { + lf_var1w=op; + lf_resw=0-lf_var1w; + lflags.type=t_NEGw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_neg_word_simple(Bit16u op) { + return 0-op; +} + +static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_inc_dword(Bit32u op) { + LoadCF; + lf_var1d=op; + lf_resd=lf_var1d+1; + lflags.type=t_INCd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_inc_dword_simple(Bit32u op) { + return op+1; +} + +static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dec_dword(Bit32u op) { + LoadCF; + lf_var1d=op; + lf_resd=lf_var1d-1; + lflags.type=t_DECd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dec_dword_simple(Bit32u op) { + return op-1; +} + +static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_not_dword(Bit32u op) { + return ~op; +} + +static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_neg_dword(Bit32u op) { + lf_var1d=op; + lf_resd=0-lf_var1d; + lflags.type=t_NEGd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_neg_dword_simple(Bit32u op) { + return 0-op; +} + + +static void dyn_sop_byte_gencall(SingleOps op) { + switch (op) { + case SOP_INC: + InvalidateFlagsPartially((void*)&dynrec_inc_byte_simple,t_INCb); + gen_call_function_raw((void*)&dynrec_inc_byte); + break; + case SOP_DEC: + InvalidateFlagsPartially((void*)&dynrec_dec_byte_simple,t_DECb); + gen_call_function_raw((void*)&dynrec_dec_byte); + break; + case SOP_NOT: + gen_call_function_raw((void*)&dynrec_not_byte); + break; + case SOP_NEG: + InvalidateFlags((void*)&dynrec_neg_byte_simple,t_NEGb); + gen_call_function_raw((void*)&dynrec_neg_byte); + break; + default: IllegalOptionDynrec("dyn_sop_byte_gencall"); + } +} + +static void dyn_sop_word_gencall(SingleOps op,bool dword) { + if (dword) { + switch (op) { + case SOP_INC: + InvalidateFlagsPartially((void*)&dynrec_inc_dword_simple,t_INCd); + gen_call_function_raw((void*)&dynrec_inc_dword); + break; + case SOP_DEC: + InvalidateFlagsPartially((void*)&dynrec_dec_dword_simple,t_DECd); + gen_call_function_raw((void*)&dynrec_dec_dword); + break; + case SOP_NOT: + gen_call_function_raw((void*)&dynrec_not_dword); + break; + case SOP_NEG: + InvalidateFlags((void*)&dynrec_neg_dword_simple,t_NEGd); + gen_call_function_raw((void*)&dynrec_neg_dword); + break; + default: IllegalOptionDynrec("dyn_sop_dword_gencall"); + } + } else { + switch (op) { + case SOP_INC: + InvalidateFlagsPartially((void*)&dynrec_inc_word_simple,t_INCw); + gen_call_function_raw((void*)&dynrec_inc_word); + break; + case SOP_DEC: + InvalidateFlagsPartially((void*)&dynrec_dec_word_simple,t_DECw); + gen_call_function_raw((void*)&dynrec_dec_word); + break; + case SOP_NOT: + gen_call_function_raw((void*)&dynrec_not_word); + break; + case SOP_NEG: + InvalidateFlags((void*)&dynrec_neg_word_simple,t_NEGw); + gen_call_function_raw((void*)&dynrec_neg_word); + break; + default: IllegalOptionDynrec("dyn_sop_word_gencall"); + } + } +} + + +static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_rol_byte(Bit8u op1,Bit8u op2) { + if (!(op2&0x7)) { + if (op2&0x18) { + FillFlagsNoCFOF(); + SETFLAGBIT(CF,op1 & 1); + SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); + } + return op1; + } + FillFlagsNoCFOF(); + lf_var1b=op1; + lf_var2b=op2&0x07; + lf_resb=(lf_var1b << lf_var2b) | (lf_var1b >> (8-lf_var2b)); + SETFLAGBIT(CF,lf_resb & 1); + SETFLAGBIT(OF,(lf_resb & 1) ^ (lf_resb >> 7)); + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_rol_byte_simple(Bit8u op1,Bit8u op2) { + if (!(op2&0x7)) return op1; + return (op1 << (op2&0x07)) | (op1 >> (8-(op2&0x07))); +} + +static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_ror_byte(Bit8u op1,Bit8u op2) { + if (!(op2&0x7)) { + if (op2&0x10) { + FillFlagsNoCFOF(); + SETFLAGBIT(CF,op1>>7); + SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); + } + return op1; + } + FillFlagsNoCFOF(); + lf_var1b=op1; + lf_var2b=op2&0x07; + lf_resb=(lf_var1b >> lf_var2b) | (lf_var1b << (8-lf_var2b)); + SETFLAGBIT(CF,lf_resb & 0x80); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_ror_byte_simple(Bit8u op1,Bit8u op2) { + if (!(op2&0x7)) return op1; + return (op1 >> (op2&0x07)) | (op1 << (8-(op2&0x07))); +} + +static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_rcl_byte(Bit8u op1,Bit8u op2) { + if (op2%9) { + Bit8u cf=(Bit8u)FillFlags()&0x1; + lf_var1b=op1; + lf_var2b=op2%9; + lf_resb=(lf_var1b << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1b >> (9-lf_var2b)); + SETFLAGBIT(CF,((lf_var1b >> (8-lf_var2b)) & 1)); + SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resb >> 7)); + return lf_resb; + } else return op1; +} + +static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_rcr_byte(Bit8u op1,Bit8u op2) { + if (op2%9) { + Bit8u cf=(Bit8u)FillFlags()&0x1; + lf_var1b=op1; + lf_var2b=op2%9; + lf_resb=(lf_var1b >> lf_var2b) | (cf << (8-lf_var2b)) | (lf_var1b << (9-lf_var2b)); \ + SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); + return lf_resb; + } else return op1; +} + +static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_shl_byte(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b << lf_var2b; + lflags.type=t_SHLb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_shl_byte_simple(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + return op1 << op2; +} + +static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_shr_byte(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1b=op1; + lf_var2b=op2; + lf_resb=lf_var1b >> lf_var2b; + lflags.type=t_SHRb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_shr_byte_simple(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + return op1 >> op2; +} + +static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sar_byte(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1b=op1; + lf_var2b=op2; + if (lf_var2b>8) lf_var2b=8; + if (lf_var1b & 0x80) { + lf_resb=(lf_var1b >> lf_var2b)| (0xff << (8 - lf_var2b)); + } else { + lf_resb=lf_var1b >> lf_var2b; + } + lflags.type=t_SARb; + return lf_resb; +} + +static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) DRC_FC; +static Bit8u DRC_CALL_CONV dynrec_sar_byte_simple(Bit8u op1,Bit8u op2) { + if (!op2) return op1; + if (op2>8) op2=8; + if (op1 & 0x80) return (op1 >> op2) | (0xff << (8 - op2)); + else return op1 >> op2; +} + +static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_rol_word(Bit16u op1,Bit8u op2) { + if (!(op2&0xf)) { + if (op2&0x10) { + FillFlagsNoCFOF(); + SETFLAGBIT(CF,op1 & 1); + SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); + } + return op1; + } + FillFlagsNoCFOF(); + lf_var1w=op1; + lf_var2b=op2&0xf; + lf_resw=(lf_var1w << lf_var2b) | (lf_var1w >> (16-lf_var2b)); + SETFLAGBIT(CF,lf_resw & 1); + SETFLAGBIT(OF,(lf_resw & 1) ^ (lf_resw >> 15)); + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_rol_word_simple(Bit16u op1,Bit8u op2) { + if (!(op2&0xf)) return op1; + return (op1 << (op2&0xf)) | (op1 >> (16-(op2&0xf))); +} + +static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_ror_word(Bit16u op1,Bit8u op2) { + if (!(op2&0xf)) { + if (op2&0x10) { + FillFlagsNoCFOF(); + SETFLAGBIT(CF,op1>>15); + SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); + } + return op1; + } + FillFlagsNoCFOF(); + lf_var1w=op1; + lf_var2b=op2&0xf; + lf_resw=(lf_var1w >> lf_var2b) | (lf_var1w << (16-lf_var2b)); + SETFLAGBIT(CF,lf_resw & 0x8000); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_ror_word_simple(Bit16u op1,Bit8u op2) { + if (!(op2&0xf)) return op1; + return (op1 >> (op2&0xf)) | (op1 << (16-(op2&0xf))); +} + +static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_rcl_word(Bit16u op1,Bit8u op2) { + if (op2%17) { + Bit16u cf=(Bit16u)FillFlags()&0x1; + lf_var1w=op1; + lf_var2b=op2%17; + lf_resw=(lf_var1w << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1w >> (17-lf_var2b)); + SETFLAGBIT(CF,((lf_var1w >> (16-lf_var2b)) & 1)); + SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resw >> 15)); + return lf_resw; + } else return op1; +} + +static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_rcr_word(Bit16u op1,Bit8u op2) { + if (op2%17) { + Bit16u cf=(Bit16u)FillFlags()&0x1; + lf_var1w=op1; + lf_var2b=op2%17; + lf_resw=(lf_var1w >> lf_var2b) | (cf << (16-lf_var2b)) | (lf_var1w << (17-lf_var2b)); + SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); + return lf_resw; + } else return op1; +} + +static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_shl_word(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1w=op1; + lf_var2b=op2; + lf_resw=lf_var1w << lf_var2b; + lflags.type=t_SHLw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_shl_word_simple(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + return op1 << op2; +} + +static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_shr_word(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1w=op1; + lf_var2b=op2; + lf_resw=lf_var1w >> lf_var2b; + lflags.type=t_SHRw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_shr_word_simple(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + return op1 >> op2; +} + +static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sar_word(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1w=op1; + lf_var2b=op2; + if (lf_var2b>16) lf_var2b=16; + if (lf_var1w & 0x8000) { + lf_resw=(lf_var1w >> lf_var2b) | (0xffff << (16 - lf_var2b)); + } else { + lf_resw=lf_var1w >> lf_var2b; + } + lflags.type=t_SARw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_sar_word_simple(Bit16u op1,Bit8u op2) { + if (!op2) return op1; + if (op2>16) op2=16; + if (op1 & 0x8000) return (op1 >> op2) | (0xffff << (16 - op2)); + else return op1 >> op2; +} + +static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_rol_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + FillFlagsNoCFOF(); + lf_var1d=op1; + lf_var2b=op2; + lf_resd=(lf_var1d << lf_var2b) | (lf_var1d >> (32-lf_var2b)); + SETFLAGBIT(CF,lf_resd & 1); + SETFLAGBIT(OF,(lf_resd & 1) ^ (lf_resd >> 31)); + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_rol_dword_simple(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + return (op1 << op2) | (op1 >> (32-op2)); +} + +static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_ror_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + FillFlagsNoCFOF(); + lf_var1d=op1; + lf_var2b=op2; + lf_resd=(lf_var1d >> lf_var2b) | (lf_var1d << (32-lf_var2b)); + SETFLAGBIT(CF,lf_resd & 0x80000000); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_ror_dword_simple(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + return (op1 >> op2) | (op1 << (32-op2)); +} + +static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_rcl_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + Bit32u cf=(Bit32u)FillFlags()&0x1; + lf_var1d=op1; + lf_var2b=op2; + if (lf_var2b==1) { + lf_resd=(lf_var1d << 1) | cf; + } else { + lf_resd=(lf_var1d << lf_var2b) | (cf << (lf_var2b-1)) | (lf_var1d >> (33-lf_var2b)); + } + SETFLAGBIT(CF,((lf_var1d >> (32-lf_var2b)) & 1)); + SETFLAGBIT(OF,(reg_flags & 1) ^ (lf_resd >> 31)); + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_rcr_dword(Bit32u op1,Bit8u op2) { + if (op2) { + Bit32u cf=(Bit32u)FillFlags()&0x1; + lf_var1d=op1; + lf_var2b=op2; + if (lf_var2b==1) { + lf_resd=lf_var1d >> 1 | cf << 31; + } else { + lf_resd=(lf_var1d >> lf_var2b) | (cf << (32-lf_var2b)) | (lf_var1d << (33-lf_var2b)); + } + SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); + return lf_resd; + } else return op1; +} + +static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_shl_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1d=op1; + lf_var2b=op2; + lf_resd=lf_var1d << lf_var2b; + lflags.type=t_SHLd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_shl_dword_simple(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + return op1 << op2; +} + +static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_shr_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + lf_var1d=op1; + lf_var2b=op2; + lf_resd=lf_var1d >> lf_var2b; + lflags.type=t_SHRd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_shr_dword_simple(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + return op1 >> op2; +} + +static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sar_dword(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + lf_var2b=op2; + lf_var1d=op1; + if (lf_var1d & 0x80000000) { + lf_resd=(lf_var1d >> lf_var2b) | (0xffffffff << (32 - lf_var2b)); + } else { + lf_resd=lf_var1d >> lf_var2b; + } + lflags.type=t_SARd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_sar_dword_simple(Bit32u op1,Bit8u op2) { + if (!op2) return op1; + if (op1 & 0x80000000) return (op1 >> op2) | (0xffffffff << (32 - op2)); + else return op1 >> op2; +} + +static void dyn_shift_byte_gencall(ShiftOps op) { + switch (op) { + case SHIFT_ROL: + InvalidateFlagsPartially((void*)&dynrec_rol_byte_simple,t_ROLb); + gen_call_function_raw((void*)&dynrec_rol_byte); + break; + case SHIFT_ROR: + InvalidateFlagsPartially((void*)&dynrec_ror_byte_simple,t_RORb); + gen_call_function_raw((void*)&dynrec_ror_byte); + break; + case SHIFT_RCL: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcl_byte); + break; + case SHIFT_RCR: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcr_byte); + break; + case SHIFT_SHL: + case SHIFT_SAL: + InvalidateFlagsPartially((void*)&dynrec_shl_byte_simple,t_SHLb); + gen_call_function_raw((void*)&dynrec_shl_byte); + break; + case SHIFT_SHR: + InvalidateFlagsPartially((void*)&dynrec_shr_byte_simple,t_SHRb); + gen_call_function_raw((void*)&dynrec_shr_byte); + break; + case SHIFT_SAR: + InvalidateFlagsPartially((void*)&dynrec_sar_byte_simple,t_SARb); + gen_call_function_raw((void*)&dynrec_sar_byte); + break; + default: IllegalOptionDynrec("dyn_shift_byte_gencall"); + } +} + +static void dyn_shift_word_gencall(ShiftOps op,bool dword) { + if (dword) { + switch (op) { + case SHIFT_ROL: + InvalidateFlagsPartially((void*)&dynrec_rol_dword_simple,t_ROLd); + gen_call_function_raw((void*)&dynrec_rol_dword); + break; + case SHIFT_ROR: + InvalidateFlagsPartially((void*)&dynrec_ror_dword_simple,t_RORd); + gen_call_function_raw((void*)&dynrec_ror_dword); + break; + case SHIFT_RCL: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcl_dword); + break; + case SHIFT_RCR: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcr_dword); + break; + case SHIFT_SHL: + case SHIFT_SAL: + InvalidateFlagsPartially((void*)&dynrec_shl_dword_simple,t_SHLd); + gen_call_function_raw((void*)&dynrec_shl_dword); + break; + case SHIFT_SHR: + InvalidateFlagsPartially((void*)&dynrec_shr_dword_simple,t_SHRd); + gen_call_function_raw((void*)&dynrec_shr_dword); + break; + case SHIFT_SAR: + InvalidateFlagsPartially((void*)&dynrec_sar_dword_simple,t_SARd); + gen_call_function_raw((void*)&dynrec_sar_dword); + break; + default: IllegalOptionDynrec("dyn_shift_dword_gencall"); + } + } else { + switch (op) { + case SHIFT_ROL: + InvalidateFlagsPartially((void*)&dynrec_rol_word_simple,t_ROLw); + gen_call_function_raw((void*)&dynrec_rol_word); + break; + case SHIFT_ROR: + InvalidateFlagsPartially((void*)&dynrec_ror_word_simple,t_RORw); + gen_call_function_raw((void*)&dynrec_ror_word); + break; + case SHIFT_RCL: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcl_word); + break; + case SHIFT_RCR: + AcquireFlags(FLAG_CF); + gen_call_function_raw((void*)&dynrec_rcr_word); + break; + case SHIFT_SHL: + case SHIFT_SAL: + InvalidateFlagsPartially((void*)&dynrec_shl_word_simple,t_SHLw); + gen_call_function_raw((void*)&dynrec_shl_word); + break; + case SHIFT_SHR: + InvalidateFlagsPartially((void*)&dynrec_shr_word_simple,t_SHRw); + gen_call_function_raw((void*)&dynrec_shr_word); + break; + case SHIFT_SAR: + InvalidateFlagsPartially((void*)&dynrec_sar_word_simple,t_SARw); + gen_call_function_raw((void*)&dynrec_sar_word); + break; + default: IllegalOptionDynrec("dyn_shift_word_gencall"); + } + } +} + +static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dshl_word(Bit16u op1,Bit16u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + lf_var2b=val; + lf_var1d=(op1<<16)|op2; + Bit32u tempd=lf_var1d << lf_var2b; + if (lf_var2b>16) tempd |= (op2 << (lf_var2b - 16)); + lf_resw=(Bit16u)(tempd >> 16); + lflags.type=t_DSHLw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dshl_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + Bit32u tempd=(Bit32u)((((Bit32u)op1)<<16)|op2) << val; + if (val>16) tempd |= (op2 << (val - 16)); + return (Bit16u)(tempd >> 16); +} + +static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dshl_dword(Bit32u op1,Bit32u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + lf_var2b=val; + lf_var1d=op1; + lf_resd=(lf_var1d << lf_var2b) | (op2 >> (32-lf_var2b)); + lflags.type=t_DSHLd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dshl_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + return (op1 << val) | (op2 >> (32-val)); +} + +static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dshr_word(Bit16u op1,Bit16u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + lf_var2b=val; + lf_var1d=(op2<<16)|op1; + Bit32u tempd=lf_var1d >> lf_var2b; + if (lf_var2b>16) tempd |= (op2 << (32-lf_var2b )); + lf_resw=(Bit16u)(tempd); + lflags.type=t_DSHRw; + return lf_resw; +} + +static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dshr_word_simple(Bit16u op1,Bit16u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + Bit32u tempd=(Bit32u)((((Bit32u)op2)<<16)|op1) >> val; + if (val>16) tempd |= (op2 << (32-val)); + return (Bit16u)(tempd); +} + +static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dshr_dword(Bit32u op1,Bit32u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + lf_var2b=val; + lf_var1d=op1; + lf_resd=(lf_var1d >> lf_var2b) | (op2 << (32-lf_var2b)); + lflags.type=t_DSHRd; + return lf_resd; +} + +static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dshr_dword_simple(Bit32u op1,Bit32u op2,Bit8u op3) { + Bit8u val=op3 & 0x1f; + if (!val) return op1; + return (op1 >> val) | (op2 << (32-val)); +} + +static void dyn_dpshift_word_gencall(bool left) { + if (left) { + DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_word,FC_RETOP); + InvalidateFlagsPartially((void*)&dynrec_dshl_word_simple,proc_addr,t_DSHLw); + } else { + DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_word,FC_RETOP); + InvalidateFlagsPartially((void*)&dynrec_dshr_word_simple,proc_addr,t_DSHRw); + } +} + +static void dyn_dpshift_dword_gencall(bool left) { + if (left) { + DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshl_dword,FC_RETOP); + InvalidateFlagsPartially((void*)&dynrec_dshl_dword_simple,proc_addr,t_DSHLd); + } else { + DRC_PTR_SIZE_IM proc_addr=gen_call_function_R3((void*)&dynrec_dshr_dword,FC_RETOP); + InvalidateFlagsPartially((void*)&dynrec_dshr_dword_simple,proc_addr,t_DSHRd); + } +} + + + +static Bit32u DRC_CALL_CONV dynrec_get_of(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_of(void) { return TFLG_O; } +static Bit32u DRC_CALL_CONV dynrec_get_nof(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_nof(void) { return TFLG_NO; } +static Bit32u DRC_CALL_CONV dynrec_get_cf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_cf(void) { return TFLG_B; } +static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_ncf(void) { return TFLG_NB; } +static Bit32u DRC_CALL_CONV dynrec_get_zf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_zf(void) { return TFLG_Z; } +static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_nzf(void) { return TFLG_NZ; } +static Bit32u DRC_CALL_CONV dynrec_get_sf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_sf(void) { return TFLG_S; } +static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_nsf(void) { return TFLG_NS; } +static Bit32u DRC_CALL_CONV dynrec_get_pf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_pf(void) { return TFLG_P; } +static Bit32u DRC_CALL_CONV dynrec_get_npf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_npf(void) { return TFLG_NP; } + +static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_cf_or_zf(void) { return TFLG_BE; } +static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_ncf_and_nzf(void) { return TFLG_NBE; } +static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_sf_neq_of(void) { return TFLG_L; } +static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_sf_eq_of(void) { return TFLG_NL; } +static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_zf_or_sf_neq_of(void) { return TFLG_LE; } +static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_get_nzf_and_sf_eq_of(void) { return TFLG_NLE; } + + +static void dyn_branchflag_to_reg(BranchTypes btype) { + switch (btype) { + case BR_O:gen_call_function_raw((void*)&dynrec_get_of);break; + case BR_NO:gen_call_function_raw((void*)&dynrec_get_nof);break; + case BR_B:gen_call_function_raw((void*)&dynrec_get_cf);break; + case BR_NB:gen_call_function_raw((void*)&dynrec_get_ncf);break; + case BR_Z:gen_call_function_raw((void*)&dynrec_get_zf);break; + case BR_NZ:gen_call_function_raw((void*)&dynrec_get_nzf);break; + case BR_BE:gen_call_function_raw((void*)&dynrec_get_cf_or_zf);break; + case BR_NBE:gen_call_function_raw((void*)&dynrec_get_ncf_and_nzf);break; + + case BR_S:gen_call_function_raw((void*)&dynrec_get_sf);break; + case BR_NS:gen_call_function_raw((void*)&dynrec_get_nsf);break; + case BR_P:gen_call_function_raw((void*)&dynrec_get_pf);break; + case BR_NP:gen_call_function_raw((void*)&dynrec_get_npf);break; + case BR_L:gen_call_function_raw((void*)&dynrec_get_sf_neq_of);break; + case BR_NL:gen_call_function_raw((void*)&dynrec_get_sf_eq_of);break; + case BR_LE:gen_call_function_raw((void*)&dynrec_get_zf_or_sf_neq_of);break; + case BR_NLE:gen_call_function_raw((void*)&dynrec_get_nzf_and_sf_eq_of);break; + } +} + + +static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) DRC_FC; +static void DRC_CALL_CONV dynrec_mul_byte(Bit8u op) { + FillFlagsNoCFOF(); + reg_ax=reg_al*op; + SETFLAGBIT(ZF,reg_al == 0); + if (reg_ax & 0xff00) { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } else { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } +} + +static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) DRC_FC; +static void DRC_CALL_CONV dynrec_imul_byte(Bit8u op) { + FillFlagsNoCFOF(); + reg_ax=((Bit8s)reg_al) * ((Bit8s)op); + if ((reg_ax & 0xff80)==0xff80 || (reg_ax & 0xff80)==0x0000) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } +} + +static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) DRC_FC; +static void DRC_CALL_CONV dynrec_mul_word(Bit16u op) { + FillFlagsNoCFOF(); + Bitu tempu=(Bitu)reg_ax*(Bitu)op; + reg_ax=(Bit16u)(tempu); + reg_dx=(Bit16u)(tempu >> 16); + SETFLAGBIT(ZF,reg_ax == 0); + if (reg_dx) { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } else { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } +} + +static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) DRC_FC; +static void DRC_CALL_CONV dynrec_imul_word(Bit16u op) { + FillFlagsNoCFOF(); + Bits temps=((Bit16s)reg_ax)*((Bit16s)op); + reg_ax=(Bit16s)(temps); + reg_dx=(Bit16s)(temps >> 16); + if (((temps & 0xffff8000)==0xffff8000 || (temps & 0xffff8000)==0x0000)) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } +} + +static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) DRC_FC; +static void DRC_CALL_CONV dynrec_mul_dword(Bit32u op) { + FillFlagsNoCFOF(); + Bit64u tempu=(Bit64u)reg_eax*(Bit64u)op; + reg_eax=(Bit32u)(tempu); + reg_edx=(Bit32u)(tempu >> 32); + SETFLAGBIT(ZF,reg_eax == 0); + if (reg_edx) { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } else { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } +} + +static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) DRC_FC; +static void DRC_CALL_CONV dynrec_imul_dword(Bit32u op) { + FillFlagsNoCFOF(); + Bit64s temps=((Bit64s)((Bit32s)reg_eax))*((Bit64s)((Bit32s)op)); + reg_eax=(Bit32u)(temps); + reg_edx=(Bit32u)(temps >> 32); + if ((reg_edx==0xffffffff) && (reg_eax & 0x80000000) ) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else if ( (reg_edx==0x00000000) && (reg_eax< 0x80000000) ) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } +} + + +static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_div_byte(Bit8u op) { + Bitu val=op; + if (val==0) return CPU_PrepareException(0,0); + Bitu quo=reg_ax / val; + Bit8u rem=(Bit8u)(reg_ax % val); + Bit8u quo8=(Bit8u)(quo&0xff); + if (quo>0xff) return CPU_PrepareException(0,0); + reg_ah=rem; + reg_al=quo8; + return false; +} + +static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_idiv_byte(Bit8u op) { + Bits val=(Bit8s)op; + if (val==0) return CPU_PrepareException(0,0); + Bits quo=((Bit16s)reg_ax) / val; + Bit8s rem=(Bit8s)((Bit16s)reg_ax % val); + Bit8s quo8s=(Bit8s)(quo&0xff); + if (quo!=(Bit16s)quo8s) return CPU_PrepareException(0,0); + reg_ah=rem; + reg_al=quo8s; + return false; +} + +static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_div_word(Bit16u op) { + Bitu val=op; + if (val==0) return CPU_PrepareException(0,0); + Bitu num=((Bit32u)reg_dx<<16)|reg_ax; + Bitu quo=num/val; + Bit16u rem=(Bit16u)(num % val); + Bit16u quo16=(Bit16u)(quo&0xffff); + if (quo!=(Bit32u)quo16) return CPU_PrepareException(0,0); + reg_dx=rem; + reg_ax=quo16; + return false; +} + +static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_idiv_word(Bit16u op) { + Bits val=(Bit16s)op; + if (val==0) return CPU_PrepareException(0,0); + Bits num=(Bit32s)((reg_dx<<16)|reg_ax); + Bits quo=num/val; + Bit16s rem=(Bit16s)(num % val); + Bit16s quo16s=(Bit16s)quo; + if (quo!=(Bit32s)quo16s) return CPU_PrepareException(0,0); + reg_dx=rem; + reg_ax=quo16s; + return false; +} + +static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_div_dword(Bit32u op) { + Bitu val=op; + if (val==0) return CPU_PrepareException(0,0); + Bit64u num=(((Bit64u)reg_edx)<<32)|reg_eax; + Bit64u quo=num/val; + Bit32u rem=(Bit32u)(num % val); + Bit32u quo32=(Bit32u)(quo&0xffffffff); + if (quo!=(Bit64u)quo32) return CPU_PrepareException(0,0); + reg_edx=rem; + reg_eax=quo32; + return false; +} + +static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) DRC_FC; +static bool DRC_CALL_CONV dynrec_idiv_dword(Bit32u op) { + Bits val=(Bit32s)op; + if (val==0) return CPU_PrepareException(0,0); + Bit64s num=(((Bit64u)reg_edx)<<32)|reg_eax; + Bit64s quo=num/val; + Bit32s rem=(Bit32s)(num % val); + Bit32s quo32s=(Bit32s)(quo&0xffffffff); + if (quo!=(Bit64s)quo32s) return CPU_PrepareException(0,0); + reg_edx=rem; + reg_eax=quo32s; + return false; +} + + +static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_dimul_word(Bit16u op1,Bit16u op2) { + FillFlagsNoCFOF(); + Bits res=((Bit16s)op1) * ((Bit16s)op2); + if ((res>-32768) && (res<32767)) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } + return (Bit16u)(res & 0xffff); +} + +static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_dimul_dword(Bit32u op1,Bit32u op2) { + FillFlagsNoCFOF(); + Bit64s res=((Bit64s)((Bit32s)op1))*((Bit64s)((Bit32s)op2)); + if ((res>-((Bit64s)(2147483647)+1)) && (res<(Bit64s)2147483647)) { + SETFLAGBIT(CF,false); + SETFLAGBIT(OF,false); + } else { + SETFLAGBIT(CF,true); + SETFLAGBIT(OF,true); + } + return (Bit32s)res; +} + + + +static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_cbw(Bit8u op) { + return (Bit8s)op; +} + +static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_cwde(Bit16u op) { + return (Bit16s)op; +} + +static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_cwd(Bit16u op) { + if (op & 0x8000) return 0xffff; + else return 0; +} + +static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_cdq(Bit32u op) { + if (op & 0x80000000) return 0xffffffff; + else return 0; +} + + +static void DRC_CALL_CONV dynrec_sahf(Bit16u op) DRC_FC; +static void DRC_CALL_CONV dynrec_sahf(Bit16u op) { + SETFLAGBIT(OF,get_OF()); + lflags.type=t_UNKNOWN; + CPU_SetFlags(op>>8,FMASK_NORMAL & 0xff); +} + + +static void DRC_CALL_CONV dynrec_cmc(void) DRC_FC; +static void DRC_CALL_CONV dynrec_cmc(void) { + FillFlags(); + SETFLAGBIT(CF,!(reg_flags & FLAG_CF)); +} +static void DRC_CALL_CONV dynrec_clc(void) DRC_FC; +static void DRC_CALL_CONV dynrec_clc(void) { + FillFlags(); + SETFLAGBIT(CF,false); +} +static void DRC_CALL_CONV dynrec_stc(void) DRC_FC; +static void DRC_CALL_CONV dynrec_stc(void) { + FillFlags(); + SETFLAGBIT(CF,true); +} +static void DRC_CALL_CONV dynrec_cld(void) DRC_FC; +static void DRC_CALL_CONV dynrec_cld(void) { + SETFLAGBIT(DF,false); + cpu.direction=1; +} +static void DRC_CALL_CONV dynrec_std(void) DRC_FC; +static void DRC_CALL_CONV dynrec_std(void) { + SETFLAGBIT(DF,true); + cpu.direction=-1; +} + + +static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_movsb_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + mem_writeb(di_base+reg_di,mem_readb(si_base+reg_si)); + reg_si+=add_index; + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_movsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + mem_writeb(di_base+reg_edi,mem_readb(si_base+reg_esi)); + reg_esi+=add_index; + reg_edi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_movsw_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + mem_writew(di_base+reg_di,mem_readw(si_base+reg_si)); + reg_si+=add_index; + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_movsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + mem_writew(di_base+reg_edi,mem_readw(si_base+reg_esi)); + reg_esi+=add_index; + reg_edi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_movsd_word(Bit16u count,Bit16s add_index,PhysPt si_base,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + mem_writed(di_base+reg_di,mem_readd(si_base+reg_si)); + reg_si+=add_index; + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_movsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + mem_writed(di_base+reg_edi,mem_readd(si_base+reg_esi)); + reg_esi+=add_index; + reg_edi+=add_index; + } + return count_left; +} + + +static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_lodsb_word(Bit16u count,Bit16s add_index,PhysPt si_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + reg_al=mem_readb(si_base+reg_si); + reg_si+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_lodsb_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + reg_al=mem_readb(si_base+reg_esi); + reg_esi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_lodsw_word(Bit16u count,Bit16s add_index,PhysPt si_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + reg_ax=mem_readw(si_base+reg_si); + reg_si+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_lodsw_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + reg_ax=mem_readw(si_base+reg_esi); + reg_esi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_lodsd_word(Bit16u count,Bit16s add_index,PhysPt si_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + reg_eax=mem_readd(si_base+reg_si); + reg_si+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_lodsd_dword(Bit32u count,Bit32s add_index,PhysPt si_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + reg_eax=mem_readd(si_base+reg_esi); + reg_esi+=add_index; + } + return count_left; +} + + +static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_stosb_word(Bit16u count,Bit16s add_index,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + mem_writeb(di_base+reg_di,reg_al); + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_stosb_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + for (;count>0;count--) { + mem_writeb(di_base+reg_edi,reg_al); + reg_edi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_stosw_word(Bit16u count,Bit16s add_index,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + mem_writew(di_base+reg_di,reg_ax); + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_stosw_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=1; + for (;count>0;count--) { + mem_writew(di_base+reg_edi,reg_ax); + reg_edi+=add_index; + } + return count_left; +} + +static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_stosd_word(Bit16u count,Bit16s add_index,PhysPt di_base) { + Bit16u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=(Bit16u)(count-CPU_Cycles); + count=(Bit16u)CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + mem_writed(di_base+reg_di,reg_eax); + reg_di+=add_index; + } + return count_left; +} + +static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_stosd_dword(Bit32u count,Bit32s add_index,PhysPt di_base) { + Bit32u count_left; + if (count<(Bitu)CPU_Cycles) { + count_left=0; + } else { + count_left=count-CPU_Cycles; + count=CPU_Cycles; + CPU_Cycles=0; + } + add_index<<=2; + for (;count>0;count--) { + mem_writed(di_base+reg_edi,reg_eax); + reg_edi+=add_index; + } + return count_left; +} + + +static void DRC_CALL_CONV dynrec_push_word(Bit16u value) DRC_FC; +static void DRC_CALL_CONV dynrec_push_word(Bit16u value) { + Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-2)&cpu.stack.mask); + mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask),value); + reg_esp=new_esp; +} + +static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) DRC_FC; +static void DRC_CALL_CONV dynrec_push_dword(Bit32u value) { + Bit32u new_esp=(reg_esp&cpu.stack.notmask)|((reg_esp-4)&cpu.stack.mask); + mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); + reg_esp=new_esp; +} + +static Bit16u DRC_CALL_CONV dynrec_pop_word(void) DRC_FC; +static Bit16u DRC_CALL_CONV dynrec_pop_word(void) { + Bit16u val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+2)&cpu.stack.mask); + return val; +} + +static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) DRC_FC; +static Bit32u DRC_CALL_CONV dynrec_pop_dword(void) { + Bit32u val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); + reg_esp=(reg_esp&cpu.stack.notmask)|((reg_esp+4)&cpu.stack.mask); + return val; +} diff --git a/src/cpu/core_dynrec/risc_mipsel32.h b/src/cpu/core_dynrec/risc_mipsel32.h new file mode 100644 index 0000000..a6718fe --- /dev/null +++ b/src/cpu/core_dynrec/risc_mipsel32.h @@ -0,0 +1,632 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +/* MIPS32 (little endian) backend by crazyc */ + + +// some configuring defines that specify the capabilities of this architecture +// or aspects of the recompiling + +// protect FC_ADDR over function calls if necessaray +// #define DRC_PROTECT_ADDR_REG + +// try to use non-flags generating functions if possible +#define DRC_FLAGS_INVALIDATION +// try to replace _simple functions by code +#define DRC_FLAGS_INVALIDATION_DCODE + +// type with the same size as a pointer +#define DRC_PTR_SIZE_IM Bit32u + +// calling convention modifier +#define DRC_CALL_CONV /* nothing */ +#define DRC_FC /* nothing */ + +// register mapping +typedef Bit8u HostReg; + +#define HOST_v0 2 +#define HOST_v1 3 +#define HOST_a0 4 +#define HOST_a1 5 +#define HOST_t4 12 +#define HOST_t5 13 +#define HOST_t6 14 +#define HOST_t7 15 +#define HOST_s0 16 +#define HOST_t8 24 +#define HOST_t9 25 +#define temp1 HOST_v1 +#define temp2 HOST_t9 + +// register that holds function return values +#define FC_RETOP HOST_v0 + +// register used for address calculations, +#define FC_ADDR HOST_s0 // has to be saved across calls, see DRC_PROTECT_ADDR_REG + +// register that holds the first parameter +#define FC_OP1 HOST_a0 + +// register that holds the second parameter +#define FC_OP2 HOST_a1 + +// register that holds byte-accessible temporary values +#define FC_TMP_BA1 HOST_t5 + +// register that holds byte-accessible temporary values +#define FC_TMP_BA2 HOST_t6 + +// temporary register for LEA +#define TEMP_REG_DRC HOST_t7 + +// save some state to improve code gen +static bool temp1_valid = false; +static Bit32u temp1_value; + +// 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((reg_dst<<11)+0x21); // addu reg_dst, $0, reg_src + cache_addw(reg_src); +} + +// move a 32bit constant value into dest_reg +static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { + if(imm < 65536) { + cache_addw((Bit16u)imm); // ori dest_reg, $0, imm + cache_addw(0x3400+dest_reg); + } else if(((Bit32s)imm < 0) && ((Bit32s)imm >= -32768)) { + cache_addw((Bit16u)imm); // addiu dest_reg, $0, imm + cache_addw(0x2400+dest_reg); + } else if(!(imm & 0xffff)) { + cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) + cache_addw(0x3c00+dest_reg); + } else { + cache_addw((Bit16u)(imm >> 16)); // lui dest_reg, %hi(imm) + cache_addw(0x3c00+dest_reg); + cache_addw((Bit16u)imm); // ori dest_reg, dest_reg, %lo(imm) + cache_addw(0x3400+(dest_reg<<5)+dest_reg); + } +} + +// this is the only place temp1 should be modified +static void INLINE mov_imm_to_temp1(Bit32u imm) { + if (temp1_valid && (temp1_value == imm)) return; + gen_mov_dword_to_reg_imm(temp1, imm); + temp1_valid = true; + temp1_value = imm; +} + +static Bit16s gen_addr_temp1(Bit32u addr) { + Bit32u hihalf = addr & 0xffff0000; + Bit16s lohalf = addr & 0xffff; + if (lohalf > 32764) { // [l,s]wl will overflow + hihalf = addr; + lohalf = 0; + } else if(lohalf < 0) hihalf += 0x10000; + mov_imm_to_temp1(hihalf); + return lohalf; +} + +// 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) { + Bit16s lohalf = gen_addr_temp1((Bit32u)data); + // alignment.... + if (dword) { + if ((Bit32u)data & 3) { + cache_addw(lohalf+3); // lwl dest_reg, 3(temp1) + cache_addw(0x8800+(temp1<<5)+dest_reg); + cache_addw(lohalf); // lwr dest_reg, 0(temp1) + cache_addw(0x9800+(temp1<<5)+dest_reg); + } else { + cache_addw(lohalf); // lw dest_reg, 0(temp1) + cache_addw(0x8C00+(temp1<<5)+dest_reg); + } + } else { + if ((Bit32u)data & 1) { + cache_addw(lohalf); // lbu dest_reg, 0(temp1) + cache_addw(0x9000+(temp1<<5)+dest_reg); + cache_addw(lohalf+1); // lbu temp2, 1(temp1) + cache_addw(0x9000+(temp1<<5)+temp2); +#if (_MIPS_ISA==MIPS32R2) || defined(PSP) + cache_addw(0x7a04); // ins dest_reg, temp2, 8, 8 + cache_addw(0x7c00+(temp2<<5)+dest_reg); +#else + cache_addw((temp2<<11)+0x200); // sll temp2, temp2, 8 + cache_addw(temp2); + cache_addw((dest_reg<<11)+0x25); // or dest_reg, temp2, dest_reg + cache_addw((temp2<<5)+dest_reg); +#endif + } else { + cache_addw(lohalf); // lhu dest_reg, 0(temp1); + cache_addw(0x9400+(temp1<<5)+dest_reg); + } + } +} + +// 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_addw(imm); // ori dest_reg, $0, imm + cache_addw(0x3400+dest_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) { + Bit16s lohalf = gen_addr_temp1((Bit32u)dest); + // alignment.... + if (dword) { + if ((Bit32u)dest & 3) { + cache_addw(lohalf+3); // swl src_reg, 3(temp1) + cache_addw(0xA800+(temp1<<5)+src_reg); + cache_addw(lohalf); // swr src_reg, 0(temp1) + cache_addw(0xB800+(temp1<<5)+src_reg); + } else { + cache_addw(lohalf); // sw src_reg, 0(temp1) + cache_addw(0xAC00+(temp1<<5)+src_reg); + } + } else { + if((Bit32u)dest & 1) { + cache_addw(lohalf); // sb src_reg, 0(temp1) + cache_addw(0xA000+(temp1<<5)+src_reg); + cache_addw((temp2<<11)+0x202); // srl temp2, src_reg, 8 + cache_addw(src_reg); + cache_addw(lohalf+1); // sb temp2, 1(temp1) + cache_addw(0xA000+(temp1<<5)+temp2); + } else { + cache_addw(lohalf); // sh src_reg, 0(temp1); + cache_addw(0xA400+(temp1<<5)+src_reg); + } + } +} + +// 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) { + Bit16s lohalf = gen_addr_temp1((Bit32u)data); + cache_addw(lohalf); // lbu dest_reg, 0(temp1) + cache_addw(0x9000+(temp1<<5)+dest_reg); +} + +// 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 INLINE gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { + gen_mov_word_to_reg_imm(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) { + Bit16s lohalf = gen_addr_temp1((Bit32u)dest); + cache_addw(lohalf); // sb src_reg, 0(temp1) + cache_addw(0xA000+(temp1<<5)+src_reg); +} + + + +// 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) { +#if (_MIPS_ISA==MIPS32R2) || defined(PSP) + cache_addw((reg<<11)+0x420); // seb reg, reg + cache_addw(0x7c00+reg); +#else + arch that lacks seb +#endif + } else { + cache_addw(0xff); // andi reg, reg, 0xff + cache_addw(0x3000+(reg<<5)+reg); + } +} + +// 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) { +#if (_MIPS_ISA==MIPS32R2) || defined(PSP) + cache_addw((reg<<11)+0x620); // seh reg, reg + cache_addw(0x7c00+reg); +#else + arch that lacks seh +#endif + } else { + cache_addw(0xffff); // andi reg, reg, 0xffff + cache_addw(0x3000+(reg<<5)+reg); + } +} + +// add a 32bit value from memory to a full register +static void gen_add(HostReg reg,void* op) { + gen_mov_word_to_reg(temp2, op, 1); + cache_addw((reg<<11)+0x21); // addu reg, reg, temp2 + cache_addw((reg<<5)+temp2); +} + +// add a 32bit constant value to a full register +static void gen_add_imm(HostReg reg,Bit32u imm) { + if(!imm) return; + if(((Bit32s)imm >= -32768) && ((Bit32s)imm < 32768)) { + cache_addw((Bit16u)imm); // addiu reg, reg, imm + cache_addw(0x2400+(reg<<5)+reg); + } else { + mov_imm_to_temp1(imm); + cache_addw((reg<<11)+0x21); // addu reg, reg, temp1 + cache_addw((reg<<5)+temp1); + } +} + +// and a 32bit constant value with a full register +static void gen_and_imm(HostReg reg,Bit32u imm) { + if(imm < 65536) { + cache_addw((Bit16u)imm); // andi reg, reg, imm + cache_addw(0x3000+(reg<<5)+reg); + } else { + mov_imm_to_temp1((Bit32u)imm); + cache_addw((reg<<11)+0x24); // and reg, temp1, reg + cache_addw((temp1<<5)+reg); + } +} + + +// move a 32bit constant value into memory +static void INLINE gen_mov_direct_dword(void* dest,Bit32u imm) { + gen_mov_dword_to_reg_imm(temp2, imm); + gen_mov_word_from_reg(temp2, 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 a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value +static void INLINE gen_add_direct_word(void* dest,Bit32u imm,bool dword) { + if(!imm) return; + gen_mov_word_to_reg(temp2, dest, dword); + gen_add_imm(temp2, imm); + gen_mov_word_from_reg(temp2, dest, dword); +} + +// add an 8bit constant value to a dword memory value +static void INLINE gen_add_direct_byte(void* dest,Bit8s imm) { + gen_add_direct_word(dest, (Bit32s)imm, 1); +} + +// subtract an 8bit constant value from a dword memory value +static void INLINE gen_sub_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 INLINE gen_sub_direct_word(void* dest,Bit32u imm,bool dword) { + gen_add_direct_word(dest, -(Bit32s)imm, dword); +} + +// 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) { + if (scale) { + cache_addw((scale_reg<<11)+(scale<<6)); // sll scale_reg, scale_reg, scale + cache_addw(scale_reg); + } + cache_addw((dest_reg<<11)+0x21); // addu dest_reg, dest_reg, scale_reg + cache_addw((dest_reg<<5)+scale_reg); + 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_addw((dest_reg<<11)+(scale<<6)); // sll dest_reg, dest_reg, scale + cache_addw(dest_reg); + } + gen_add_imm(dest_reg, imm); +} + +#define DELAY cache_addd(0) // nop + +// generate a call to a parameterless function +static void INLINE gen_call_function_raw(void * func) { +#if C_DEBUG + if ((cache.pos ^ func) & 0xf0000000) LOG_MSG("jump overflow\n"); +#endif + temp1_valid = false; + cache_addd(0x0c000000+(((Bit32u)func>>2)&0x3ffffff)); // jal func + DELAY; +} + +// 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; +} + +#ifdef __mips_eabi +// max of 8 parameters in $a0-$a3 and $t0-$t3 + +// 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+4, 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+4, 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+4, 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+4, (void *)mem, 1); +} +#else + other mips abis +#endif + +// jump to an address pointed at by ptr, offset is in imm +static void INLINE gen_jmp_ptr(void * ptr,Bits imm=0) { + gen_mov_word_to_reg(temp2, ptr, 1); + if((imm < -32768) || (imm >= 32768)) { + gen_add_imm(temp2, imm); + imm = 0; + } + temp1_valid = false; + cache_addw((Bit16u)imm); // lw temp2, imm(temp2) + cache_addw(0x8C00+(temp2<<5)+temp2); + cache_addd((temp2<<21)+8); // jr temp2 + DELAY; +} + +// short conditional jump (+-127 bytes) if register is zero +// the destination is set by gen_fill_branch() later +static Bit32u INLINE gen_create_branch_on_zero(HostReg reg,bool dword) { + temp1_valid = false; + if(!dword) { + cache_addw(0xffff); // andi temp1, reg, 0xffff + cache_addw(0x3000+(reg<<5)+temp1); + } + cache_addw(0); // beq $0, reg, 0 + cache_addw(0x1000+(dword?reg:temp1)); + DELAY; + return ((Bit32u)cache.pos-8); +} + +// short conditional jump (+-127 bytes) if register is nonzero +// the destination is set by gen_fill_branch() later +static Bit32u INLINE gen_create_branch_on_nonzero(HostReg reg,bool dword) { + temp1_valid = false; + if(!dword) { + cache_addw(0xffff); // andi temp1, reg, 0xffff + cache_addw(0x3000+(reg<<5)+temp1); + } + cache_addw(0); // bne $0, reg, 0 + cache_addw(0x1400+(dword?reg:temp1)); + DELAY; + return ((Bit32u)cache.pos-8); +} + +// 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; + if (len<0) len=-len; + if (len>126) LOG_MSG("Big jump %d",len); +#endif + temp1_valid = false; // this is a branch target + *(Bit16u*)data=((Bit16u)((Bit32u)cache.pos-data-4)>>2); +} + +#if 0 // assume for the moment no branch will go farther then +/- 128KB + +// 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) { + temp1_valid = false; + if (!isdword) { + cache_addw(0xff); // andi temp1, reg, 0xff + cache_addw(0x3000+(reg<<5)+temp1); + } + cache_addw(3); // beq $0, reg, +12 + cache_addw(0x1000+(isdword?reg:temp1)); + DELAY; + cache_addd(0x00000000); // fill j + DELAY; + return ((Bit32u)cache.pos-8); +} + +// compare 32bit-register against zero and jump if value less/equal than zero +static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { + temp1_valid = false; + cache_addw(3); // bgtz reg, +12 + cache_addw(0x1c00+(reg<<5)); + DELAY; + cache_addd(0x00000000); // fill j + DELAY; + return ((Bit32u)cache.pos-8); +} + +// calculate long relative offset and fill it into the location pointed to by data +static void INLINE gen_fill_branch_long(Bit32u data) { + temp1_valid = false; + // this is an absolute branch + *(Bit32u*)data=0x08000000+(((Bit32u)cache.pos>>2)&0x3ffffff); +} +#else +// 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) { + temp1_valid = false; + if (!isdword) { + cache_addw(0xff); // andi temp1, reg, 0xff + cache_addw(0x3000+(reg<<5)+temp1); + } + cache_addw(0); // bne $0, reg, 0 + cache_addw(0x1400+(isdword?reg:temp1)); + DELAY; + return ((Bit32u)cache.pos-8); +} + +// compare 32bit-register against zero and jump if value less/equal than zero +static Bit32u INLINE gen_create_branch_long_leqzero(HostReg reg) { + temp1_valid = false; + cache_addw(0); // blez reg, 0 + cache_addw(0x1800+(reg<<5)); + DELAY; + return ((Bit32u)cache.pos-8); +} + +// calculate long relative offset and fill it into the location pointed to by data +static void INLINE gen_fill_branch_long(Bit32u data) { + gen_fill_branch(data); +} +#endif + +static void gen_run_code(void) { + temp1_valid = false; + cache_addd(0x27bdfff0); // addiu $sp, $sp, -16 + cache_addd(0xafb00004); // sw $s0, 4($sp) + cache_addd(0x00800008); // jr $a0 + cache_addd(0xafbf0000); // sw $ra, 0($sp) +} + +// return from a function +static void gen_return_function(void) { + temp1_valid = false; + cache_addd(0x8fbf0000); // lw $ra, 0($sp) + cache_addd(0x8fb00004); // lw $s0, 4($sp) + cache_addd(0x03e00008); // jr $ra + cache_addd(0x27bd0010); // addiu $sp, $sp, 16 +} + +#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=0x00851021; // addu $v0, $a0, $a1 + break; + case t_ORb: + case t_ORw: + case t_ORd: + *(Bit32u*)pos=0x00851025; // or $v0, $a0, $a1 + break; + case t_ANDb: + case t_ANDw: + case t_ANDd: + *(Bit32u*)pos=0x00851024; // and $v0, $a0, $a1 + break; + case t_SUBb: + case t_SUBw: + case t_SUBd: + *(Bit32u*)pos=0x00851023; // subu $v0, $a0, $a1 + break; + case t_XORb: + case t_XORw: + case t_XORd: + *(Bit32u*)pos=0x00851026; // xor $v0, $a0, $a1 + break; + case t_CMPb: + case t_CMPw: + case t_CMPd: + case t_TESTb: + case t_TESTw: + case t_TESTd: + *(Bit32u*)pos=0; // nop + break; + case t_INCb: + case t_INCw: + case t_INCd: + *(Bit32u*)pos=0x24820001; // addiu $v0, $a0, 1 + break; + case t_DECb: + case t_DECw: + case t_DECd: + *(Bit32u*)pos=0x2482ffff; // addiu $v0, $a0, -1 + break; + case t_SHLb: + case t_SHLw: + case t_SHLd: + *(Bit32u*)pos=0x00a41004; // sllv $v0, $a0, $a1 + break; + case t_SHRb: + case t_SHRw: + case t_SHRd: + *(Bit32u*)pos=0x00a41006; // srlv $v0, $a0, $a1 + break; + case t_SARd: + *(Bit32u*)pos=0x00a41007; // srav $v0, $a0, $a1 + break; +#if (_MIPS_ISA==MIPS32R2) || defined(PSP) + case t_RORd: + *(Bit32u*)pos=0x00a41046; // rotr $v0, $a0, $a1 + break; +#endif + case t_NEGb: + case t_NEGw: + case t_NEGd: + *(Bit32u*)pos=0x00041023; // subu $v0, $0, $a0 + break; + default: + *(Bit32u*)pos=0x0c000000+((((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func + break; + } +#else + *(Bit32u*)pos=0x0c000000+(((Bit32u)fct_ptr)>>2)&0x3ffffff); // jal simple_func +#endif +} +#endif diff --git a/src/cpu/core_dynrec/risc_x64.h b/src/cpu/core_dynrec/risc_x64.h new file mode 100644 index 0000000..8c71f53 --- /dev/null +++ b/src/cpu/core_dynrec/risc_x64.h @@ -0,0 +1,598 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +// some configuring defines that specify the capabilities of this architecture +// or aspects of the recompiling + +// protect FC_ADDR over function calls if necessaray +// #define DRC_PROTECT_ADDR_REG + +// try to use non-flags generating functions if possible +#define DRC_FLAGS_INVALIDATION +// try to replace _simple functions by code +// #define DRC_FLAGS_INVALIDATION_DCODE + +// type with the same size as a pointer +#define DRC_PTR_SIZE_IM Bit64u + +// calling convention modifier +#define DRC_CALL_CONV /* nothing */ +#define DRC_FC /* nothing */ + + +// register mapping +typedef Bit8u HostReg; + +#define HOST_EAX 0 +#define HOST_ECX 1 +#define HOST_EDX 2 +#define HOST_EBX 3 +#define HOST_ESI 6 +#define HOST_EDI 7 + + +// register that holds function return values +#define FC_RETOP HOST_EAX + +// register used for address calculations, if the ABI does not +// state that this register is preserved across function calls +// then define DRC_PROTECT_ADDR_REG above +#define FC_ADDR HOST_EBX + +// register that holds the first parameter +#define FC_OP1 HOST_EDI + +// register that holds the second parameter +#define FC_OP2 HOST_ESI + +// register that holds byte-accessible temporary values +#define FC_TMP_BA1 HOST_ECX + +// register that holds byte-accessible temporary values +#define FC_TMP_BA2 HOST_EDX + + +// temporary register for LEA +#define TEMP_REG_DRC HOST_ESI + + +// move a full register from reg_src to reg_dst +static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { + cache_addb(0x8b); // mov reg_dst,reg_src + cache_addb(0xc0+(reg_dst<<3)+reg_src); +} + + +static INLINE void gen_memaddr(HostReg reg,void* data) { + Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5); + if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { + cache_addb(0x05+(reg<<3)); + // RIP-relative addressing is offset after the instruction + cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); + } else if ((Bit64u)data<0x100000000LL) { + cache_addw(0x2504+(reg<<3)); + cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); + } else { + E_Exit("DRC64:Unhandled memory reference"); + } +} + + +// 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_memaddr(dest_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); +} + +// move a 32bit constant value into dest_reg +static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { + cache_addb(0xb8+dest_reg); // mov reg,imm + cache_addd(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_memaddr(src_reg,dest); +} + +// 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) { + cache_addb(0x8a); // mov reg,[data] + gen_memaddr(dest_reg,data); +} + +// 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 gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { + cache_addb(0x66); + cache_addb(0x8b); // mov reg,[data] + gen_memaddr(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_addb(0xb0+dest_reg); // mov reg,imm + cache_addb(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 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); +} + +// 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_memaddr(src_reg,dest); +} + + + +// 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) { + cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx + cache_addb(0xc0+(reg<<3)+reg); +} + +// 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) { + cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx + cache_addb(0xc0+(reg<<3)+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_memaddr(reg,op); +} + +// add a 32bit constant value to a full register +static void gen_add_imm(HostReg reg,Bit32u imm) { + cache_addw(0xc081+(reg<<8)); // add reg,imm + cache_addd(imm); +} + +// and a 32bit constant value with a full register +static void gen_and_imm(HostReg reg,Bit32u imm) { + cache_addw(0xe081+(reg<<8)); // and reg,imm + cache_addd(imm); +} + + + +// move a 32bit constant value into memory +static void gen_mov_direct_dword(void* dest,Bit32u imm) { + cache_addw(0x04c7); // mov [data],imm + cache_addb(0x25); + cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); + cache_addd(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); +} + + +// add an 8bit constant value to a memory value +static void gen_add_direct_byte(void* dest,Bit8s imm) { + cache_addw(0x0483); // add [data],imm + cache_addb(0x25); + cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); + cache_addb(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<128) && dword) { + gen_add_direct_byte(dest,(Bit8s)imm); + return; + } + if (!dword) cache_addb(0x66); + cache_addw(0x0481); // add [data],imm + cache_addb(0x25); + cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); + if (dword) cache_addd((Bit32u)imm); + else cache_addw((Bit16u)imm); +} + +// subtract an 8bit constant value from a memory value +static void gen_sub_direct_byte(void* dest,Bit8s imm) { + cache_addw(0x2c83); // sub [data],imm + cache_addb(0x25); + cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); + cache_addb(imm); +} + +// 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<128) && dword) { + gen_sub_direct_byte(dest,(Bit8s)imm); + return; + } + if (!dword) cache_addb(0x66); + cache_addw(0x2c81); // sub [data],imm + cache_addb(0x25); + cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); + if (dword) cache_addd((Bit32u)imm); + else cache_addw((Bit16u)imm); +} + + + +// 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) { + Bit8u rm_base; + Bitu imm_size; + if (!imm) { + imm_size=0; rm_base=0x0; //no imm + } else if ((imm>=-128 && imm<=127)) { + imm_size=1; rm_base=0x40; //Signed byte imm + } else { + imm_size=4; rm_base=0x80; //Signed dword imm + } + + // ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm + // ea_reg := op1 + op2 *(2^scale)+imm + cache_addb(0x48); + cache_addb(0x8d); //LEA + cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator + cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6)); + + switch (imm_size) { + case 0: break; + case 1:cache_addb(imm);break; + case 4:cache_addd(imm);break; + } +} + +// 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) { + // ea_reg := ea_reg*(2^scale)+imm + // ea_reg := op2 *(2^scale)+imm + cache_addb(0x48); + cache_addb(0x8d); //LEA + cache_addb(0x04+(dest_reg<<3)); + cache_addb(0x05+(dest_reg<<3)+(scale<<6)); + + cache_addd(imm); // always add dword immediate +} + + + +// generate a call to a parameterless function +static void INLINE gen_call_function_raw(void * func) { + cache_addb(0x48); + cache_addb(0xb8); // mov reg,imm64 + cache_addq((Bit64u)func); + cache_addw(0xd0ff); +} + +// 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); + + cache_addb(0x50); // push rax (==old rsp) + + Bit64u proc_addr=(Bit64u)cache.pos; + + // 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 + + return proc_addr; +} + + +// load an immediate value as param'th function parameter +static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { + // move an immediate 32bit value into a 64bit param reg + switch (param) { + case 0: // mov param1,imm32 + gen_mov_dword_to_reg_imm(FC_OP1,(Bit32u)imm); + break; + 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); + break; + case 3: // mov r9,imm32 + cache_addw(0xb949); + cache_addq((Bit32u)imm); + break; +#else + case 2: // mov rdx,imm32 + gen_mov_dword_to_reg_imm(HOST_EDX,(Bit32u)imm); + break; + case 3: // mov rcx,imm32 + gen_mov_dword_to_reg_imm(HOST_ECX,(Bit32u)imm); + break; +#endif + default: + E_Exit("I(mm) >4 params unsupported"); + break; + } +} + +// load an address as param'th function parameter +static void INLINE gen_load_param_addr(DRC_PTR_SIZE_IM addr,Bitu param) { + // move an immediate 64bit value into a 64bit param reg + switch (param) { + case 0: // mov param1,addr64 + gen_mov_reg_qword(FC_OP1,addr); + break; + case 1: // mov param2,addr64 + gen_mov_reg_qword(FC_OP2,addr); + break; +#if defined (_MSC_VER) + case 2: // mov r8,addr64 + cache_addw(0xb849); + cache_addq(addr); + break; + case 3: // mov r9,addr64 + cache_addw(0xb949); + cache_addq(addr); + break; +#else + case 2: // mov rdx,addr64 + gen_mov_reg_qword(HOST_EDX,addr); + break; + case 3: // mov rcx,addr64 + gen_mov_reg_qword(HOST_ECX,addr); + break; +#endif + default: + E_Exit("A(ddr) >4 params unsupported"); + break; + } +} + +// load a host-register as param'th function parameter +static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { + // move a register into a 64bit param reg, {inputregs}!={outputregs} + switch (param) { + case 0: // mov param1,reg&7 + gen_mov_regs(FC_OP1,reg&7); + break; + case 1: // mov param2,reg&7 + gen_mov_regs(FC_OP2,reg&7); + break; +#if defined (_MSC_VER) + case 2: // mov r8,reg&7 + cache_addb(0x49); + gen_mov_regs(0,reg&7); + break; + case 3: // mov r9,reg&7 + cache_addb(0x49); + gen_mov_regs(1,reg&7); + break; +#else + case 2: // mov rdx,reg&7 + gen_mov_regs(HOST_EDX,reg&7); + break; + case 3: // mov rcx,reg&7 + gen_mov_regs(HOST_ECX,reg&7); + break; +#endif + default: + E_Exit("R(eg) >4 params unsupported"); + break; + } +} + +// load a value from memory as param'th function parameter +static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { + // move memory content into a 64bit param reg + switch (param) { + case 0: // mov param1,[mem] + gen_mov_word_to_reg(FC_OP1,(void*)mem,true); + break; + 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); + break; + case 3: // mov r9,[mem] + cache_addb(0x49); + gen_mov_word_to_reg(1,(void*)mem,true); + break; +#else + case 2: // mov rdx,[mem] + gen_mov_word_to_reg(HOST_EDX,(void*)mem,true); + break; + case 3: // mov rcx,[mem] + gen_mov_word_to_reg(HOST_ECX,(void*)mem,true); + break; +#endif + default: + E_Exit("R(eg) >4 params unsupported"); + break; + } +} + + + +// jump to an address pointed at by ptr, offset is in imm +static void gen_jmp_ptr(void * ptr,Bits imm=0) { + cache_addw(0xa148); // mov rax,[data] + cache_addq((Bit64u)ptr); + + cache_addb(0xff); // jmp [rax+imm] + if (!imm) { + cache_addb(0x20); + } else if ((imm>=-128 && imm<=127)) { + cache_addb(0x60); + cache_addb(imm); + } else { + cache_addb(0xa0); + cache_addd(imm); + } +} + + +// short conditional jump (+-127 bytes) if register is zero +// the destination is set by gen_fill_branch() later +static Bit64u gen_create_branch_on_zero(HostReg reg,bool dword) { + if (!dword) cache_addb(0x66); + cache_addb(0x0b); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x0074); // jz addr + return ((Bit64u)cache.pos-1); +} + +// short conditional jump (+-127 bytes) if register is nonzero +// the destination is set by gen_fill_branch() later +static Bit64u gen_create_branch_on_nonzero(HostReg reg,bool dword) { + if (!dword) cache_addb(0x66); + cache_addb(0x0b); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x0075); // jnz addr + return ((Bit64u)cache.pos-1); +} + +// calculate relative offset and fill it into the location pointed to by data +static void gen_fill_branch(DRC_PTR_SIZE_IM data) { +#if C_DEBUG + Bit64s len=(Bit64u)cache.pos-data; + if (len<0) len=-len; + if (len>126) LOG_MSG("Big jump %d",len); +#endif + *(Bit8u*)data=(Bit8u)((Bit64u)cache.pos-data-1); +} + +// 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 Bit64u gen_create_branch_long_nonzero(HostReg reg,bool isdword) { + // isdword: cmp reg32,0 + // not isdword: cmp reg8,0 + cache_addb(0x0a+(isdword?1:0)); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x850f); // jnz + cache_addd(0); + return ((Bit64u)cache.pos-4); +} + +// compare 32bit-register against zero and jump if value less/equal than zero +static Bit64u gen_create_branch_long_leqzero(HostReg reg) { + cache_addw(0xf883+(reg<<8)); + cache_addb(0x00); // cmp reg,0 + + cache_addw(0x8e0f); // jle + cache_addd(0); + return ((Bit64u)cache.pos-4); +} + +// calculate long relative offset and fill it into the location pointed to by data +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 +} + +// return from a function +static void gen_return_function(void) { + cache_addb(0xc3); // ret +} + +#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) { + *(Bit64u*)(pos+2)=(Bit64u)fct_ptr; +} +#endif diff --git a/src/cpu/core_dynrec/risc_x86.h b/src/cpu/core_dynrec/risc_x86.h new file mode 100644 index 0000000..5fe1dfd --- /dev/null +++ b/src/cpu/core_dynrec/risc_x86.h @@ -0,0 +1,507 @@ +/* + * Copyright (C) 2002-2007 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. + */ + + +// some configuring defines that specify the capabilities of this architecture +// or aspects of the recompiling + +// protect FC_ADDR over function calls if necessaray +// #define DRC_PROTECT_ADDR_REG + +// try to use non-flags generating functions if possible +#define DRC_FLAGS_INVALIDATION +// try to replace _simple functions by code +#define DRC_FLAGS_INVALIDATION_DCODE + +// type with the same size as a pointer +#define DRC_PTR_SIZE_IM Bit32u + +// calling convention modifier +#if defined (WIN32) +#define DRC_CALL_CONV _fastcall +#define DRC_FC /* nothing */ +#else +#define DRC_CALL_CONV /* nothing */ +#define DRC_FC GCC_ATTRIBUTE(fastcall) +#endif + + +// register mapping +enum HostReg { + HOST_EAX=0, + HOST_ECX, + HOST_EDX, + HOST_EBX, + HOST_ESP, + HOST_EBP, + HOST_ESI, + HOST_EDI +}; + + +// register that holds function return values +#define FC_RETOP HOST_EAX + +// register used for address calculations, if the ABI does not +// state that this register is preserved across function calls +// then define DRC_PROTECT_ADDR_REG above +#define FC_ADDR HOST_EBX + +// register that holds the first parameter +#define FC_OP1 HOST_ECX + +// register that holds the second parameter +#define FC_OP2 HOST_EDX + +// register that holds byte-accessible temporary values +#define FC_TMP_BA1 HOST_ECX + +// register that holds byte-accessible temporary values +#define FC_TMP_BA2 HOST_EDX + + +// temporary register for LEA +#define TEMP_REG_DRC HOST_ESI + + +// move a full register from reg_src to reg_dst +static void gen_mov_regs(HostReg reg_dst,HostReg reg_src) { + cache_addb(0x8b); // mov reg_dst,reg_src + cache_addb(0xc0+(reg_dst<<3)+reg_src); +} + +// 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_addw(0x058b+(dest_reg<<11)); // mov reg,[data] + cache_addd((Bit32u)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); +} + +// move a 32bit constant value into dest_reg +static void gen_mov_dword_to_reg_imm(HostReg dest_reg,Bit32u imm) { + cache_addb(0xb8+dest_reg); // mov reg,imm + cache_addd(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_addw(0x0589+(src_reg<<11)); // mov [data],reg + cache_addd((Bit32u)dest); +} + +// 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) { + cache_addw(0x058a+(dest_reg<<11)); // mov reg,[data] + cache_addd((Bit32u)data); +} + +// 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 gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { + cache_addb(0x66); + cache_addw(0x058b+(dest_reg<<11)); // mov reg,[data] + cache_addd((Bit32u)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_addb(0xb0+dest_reg); // mov reg,imm + cache_addb(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 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); +} + +// move the lowest 8bit of a register into memory +static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { + cache_addw(0x0588+(src_reg<<11)); // mov [data],reg + cache_addd((Bit32u)dest); +} + + + +// 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) { + cache_addw(0xb60f+(sign?0x800:0)); // movsx/movzx + cache_addb(0xc0+(reg<<3)+reg); +} + +// 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) { + cache_addw(0xb70f+(sign?0x800:0)); // movsx/movzx + cache_addb(0xc0+(reg<<3)+reg); +} + + + +// add a 32bit value from memory to a full register +static void gen_add(HostReg reg,void* op) { + cache_addw(0x0503+(reg<<11)); // add reg,[data] + cache_addd((Bit32u)op); +} + +// add a 32bit constant value to a full register +static void gen_add_imm(HostReg reg,Bit32u imm) { + cache_addw(0xc081+(reg<<8)); // add reg,imm + cache_addd(imm); +} + +// and a 32bit constant value with a full register +static void gen_and_imm(HostReg reg,Bit32u imm) { + cache_addw(0xe081+(reg<<8)); // and reg,imm + cache_addd(imm); +} + + + +// move a 32bit constant value into memory +static void gen_mov_direct_dword(void* dest,Bit32u imm) { + cache_addw(0x05c7); // mov [data],imm + cache_addd((Bit32u)dest); + cache_addd(imm); +} + +// 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 memory value +static void gen_add_direct_byte(void* dest,Bit8s imm) { + cache_addw(0x0583); // add [data],imm + cache_addd((Bit32u)dest); + cache_addb(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<128) && dword) { + gen_add_direct_byte(dest,(Bit8s)imm); + return; + } + if (!dword) cache_addb(0x66); + cache_addw(0x0581); // add [data],imm + cache_addd((Bit32u)dest); + if (dword) cache_addd((Bit32u)imm); + else cache_addw((Bit16u)imm); +} + +// subtract an 8bit constant value from a memory value +static void gen_sub_direct_byte(void* dest,Bit8s imm) { + cache_addw(0x2d83); // sub [data],imm + cache_addd((Bit32u)dest); + cache_addb(imm); +} + +// 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<128) && dword) { + gen_sub_direct_byte(dest,(Bit8s)imm); + return; + } + if (!dword) cache_addb(0x66); + cache_addw(0x2d81); // sub [data],imm + cache_addd((Bit32u)dest); + if (dword) cache_addd((Bit32u)imm); + else cache_addw((Bit16u)imm); +} + + + +// 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) { + Bit8u rm_base; + Bitu imm_size; + if (!imm) { + imm_size=0; rm_base=0x0; //no imm + } else if ((imm>=-128 && imm<=127)) { + imm_size=1; rm_base=0x40; //Signed byte imm + } else { + imm_size=4; rm_base=0x80; //Signed dword imm + } + + // ea_reg := ea_reg+TEMP_REG_DRC*(2^scale)+imm + // ea_reg := op1 + op2 *(2^scale)+imm + cache_addb(0x8d); //LEA + cache_addb(0x04+(dest_reg << 3)+rm_base); //The sib indicator + cache_addb(dest_reg+(TEMP_REG_DRC<<3)+(scale<<6)); + + switch (imm_size) { + case 0: break; + case 1:cache_addb(imm);break; + case 4:cache_addd(imm);break; + } +} + +// 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) { + // ea_reg := ea_reg*(2^scale)+imm + // ea_reg := op2 *(2^scale)+imm + cache_addb(0x8d); //LEA + cache_addb(0x04+(dest_reg<<3)); + cache_addb(0x05+(dest_reg<<3)+(scale<<6)); + + cache_addd(imm); // always add dword immediate +} + + + +// generate a call to a parameterless function +static void INLINE gen_call_function_raw(void * func) { + cache_addb(0xe8); + cache_addd((Bit32u)func - (Bit32u)cache.pos-4); +} + +// 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; + // Do the actual call to the procedure + cache_addb(0xe8); + cache_addd((Bit32u)func - (Bit32u)cache.pos-4); + + // Restore the params of the stack + if (paramcount) { + cache_addw(0xc483); //add ESP,imm byte + cache_addb((!fastcall)?paramcount*4:0); + } + return proc_addr; +} + + +// load an immediate value as param'th function parameter +static void INLINE gen_load_param_imm(Bitu imm,Bitu param) { + cache_addb(0x68); // push immediate + cache_addd(imm); +} + +// load an address as param'th function parameter +static void INLINE gen_load_param_addr(Bitu addr,Bitu param) { + cache_addb(0x68); // push immediate (address) + cache_addd(addr); +} + +// load a host-register as param'th function parameter +static void INLINE gen_load_param_reg(Bitu reg,Bitu param) { + cache_addb(0x50+(reg&7)); // push reg +} + +// load a value from memory as param'th function parameter +static void INLINE gen_load_param_mem(Bitu mem,Bitu param) { + cache_addw(0x35ff); // push [] + cache_addd(mem); +} + + + +// jump to an address pointed at by ptr, offset is in imm +static void gen_jmp_ptr(void * ptr,Bits imm=0) { + gen_mov_word_to_reg(HOST_EAX,ptr,true); + cache_addb(0xff); // jmp [eax+imm] + if (!imm) { + cache_addb(0x20); + } else if ((imm>=-128 && imm<=127)) { + cache_addb(0x60); + cache_addb(imm); + } else { + cache_addb(0xa0); + cache_addd(imm); + } +} + + +// 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_addb(0x66); + cache_addb(0x0b); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x0074); // jz addr + return ((Bit32u)cache.pos-1); +} + +// 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_addb(0x66); + cache_addb(0x0b); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x0075); // jnz addr + return ((Bit32u)cache.pos-1); +} + +// calculate relative offset and fill it into the location pointed to by data +static void gen_fill_branch(DRC_PTR_SIZE_IM data) { +#if C_DEBUG + Bits len=(Bit32u)cache.pos-data; + if (len<0) len=-len; + if (len>126) LOG_MSG("Big jump %d",len); +#endif + *(Bit8u*)data=(Bit8u)((Bit32u)cache.pos-data-1); +} + +// 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) { + // isdword: cmp reg32,0 + // not isdword: cmp reg8,0 + cache_addb(0x0a+(isdword?1:0)); // or reg,reg + cache_addb(0xc0+reg+(reg<<3)); + + cache_addw(0x850f); // jnz + cache_addd(0); + 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_addw(0xf883+(reg<<8)); + cache_addb(0x00); // cmp reg,0 + + cache_addw(0x8e0f); // jle + cache_addd(0); + return ((Bit32u)cache.pos-4); +} + +// calculate long relative offset and fill it into the location pointed to by data +static void gen_fill_branch_long(Bit32u data) { + *(Bit32u*)data=((Bit32u)cache.pos-data-4); +} + + +static void gen_run_code(void) { + cache_addd(0x0424448b); // mov eax,[esp+4] + cache_addb(0x53); // push ebx + cache_addw(0xd0ff); // call eax + cache_addb(0x5b); // pop ebx +} + +// return from a function +static void gen_return_function(void) { + cache_addb(0xc3); // ret +} + +#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=0xc203c18b; + *(pos+4)=0x90; + break; + case t_ORb: + case t_ORw: + case t_ORd: + *(Bit32u*)pos=0xc20bc18b; + *(pos+4)=0x90; + break; + case t_ANDb: + case t_ANDw: + case t_ANDd: + *(Bit32u*)pos=0xc223c18b; + *(pos+4)=0x90; + break; + case t_SUBb: + case t_SUBw: + case t_SUBd: + *(Bit32u*)pos=0xc22bc18b; + *(pos+4)=0x90; + break; + case t_XORb: + case t_XORw: + case t_XORd: + *(Bit32u*)pos=0xc233c18b; + *(pos+4)=0x90; + break; + case t_CMPb: + case t_CMPw: + case t_CMPd: + case t_TESTb: + case t_TESTw: + case t_TESTd: + *(Bit32u*)pos=0x909003eb; + *(pos+4)=0x90; + break; + case t_INCb: + case t_INCw: + case t_INCd: + *(Bit32u*)pos=0x9040c18b; + *(pos+4)=0x90; + break; + case t_DECb: + case t_DECw: + case t_DECd: + *(Bit32u*)pos=0x9048c18b; + *(pos+4)=0x90; + break; + case t_NEGb: + case t_NEGw: + case t_NEGd: + *(Bit32u*)pos=0xd8f7c18b; + *(pos+4)=0x90; + break; + default: + *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); + break; + } +#else + *(Bit32u*)(pos+1)=(Bit32u)((Bit8u*)fct_ptr - (pos+1+4)); +#endif +} +#endif diff --git a/src/cpu/core_full/load.h b/src/cpu/core_full/load.h index 1f47b88..ec63d57 100644 --- a/src/cpu/core_full/load.h +++ b/src/cpu/core_full/load.h @@ -284,14 +284,12 @@ l_M_Ed: inst_op1_d=4; break; case D_IRETw: - FillFlags(); CPU_IRET(false,GetIP()); if (GETFLAG(IF) && PIC_IRQCheck) { return CBRET_NONE; } continue; case D_IRETd: - FillFlags(); CPU_IRET(true,GetIP()); if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE; @@ -407,12 +405,10 @@ l_M_Ed: cpu.direction=-1; goto nextopcode; case D_PUSHF: - FillFlags(); if (CPU_PUSHF(inst.code.extra)) RunException(); goto nextopcode; case D_POPF: if (CPU_POPF(inst.code.extra)) RunException(); - lflags.type=t_UNKNOWN; if (GETFLAG(IF) && PIC_IRQCheck) { SaveIP(); return CBRET_NONE; @@ -481,7 +477,6 @@ l_M_Ed: cpu.cr0&=(~CR0_TASKSWITCH); goto nextopcode; case D_ICEBP: - FillFlags(); CPU_SW_Interrupt_NoIOPLCheck(1,GetIP()); continue; default: diff --git a/src/cpu/core_full/loadwrite.h b/src/cpu/core_full/loadwrite.h index 37670d2..aca53c4 100644 --- a/src/cpu/core_full/loadwrite.h +++ b/src/cpu/core_full/loadwrite.h @@ -3,7 +3,6 @@ #define GetIP() (inst.cseip-SegBase(cs)) #define RunException() { \ - FillFlags(); \ CPU_Exception(cpu.exception.which,cpu.exception.error); \ continue; \ } diff --git a/src/cpu/core_full/op.h b/src/cpu/core_full/op.h index d7a454f..ed407a3 100644 --- a/src/cpu/core_full/op.h +++ b/src/cpu/core_full/op.h @@ -338,8 +338,8 @@ switch (inst.code.op) { CPU_JMP(true,inst_op2_d,inst_op1_d,GetIP()); continue; case O_INT: - FillFlags(); #if C_DEBUG + FillFlags(); if (((inst.entry & 0xFF)==0xcc) && DEBUG_Breakpoint()) return debugCallback; else if (DEBUG_IntBreakpoint(inst_op1_b)) @@ -379,18 +379,10 @@ switch (inst.code.op) { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; switch (inst.rm_index) { case 0x00: /* SLDT */ - { - Bitu selector; - CPU_SLDT(selector); - inst_op1_d=(Bit32u)selector; - } + inst_op1_d=(Bit32u)CPU_SLDT(); break; case 0x01: /* STR */ - { - Bitu selector; - CPU_STR(selector); - inst_op1_d=(Bit32u)selector; - } + inst_op1_d=(Bit32u)CPU_STR(); break; case 0x02: /* LLDT */ if (cpu.cpl) EXCEPTION(EXCEPTION_GP); @@ -401,11 +393,9 @@ switch (inst.code.op) { if (CPU_LTR(inst_op1_d)) RunException(); goto nextopcode; /* Else value will saved */ case 0x04: /* VERR */ - FillFlags(); CPU_VERR(inst_op1_d); goto nextopcode; /* Else value will saved */ case 0x05: /* VERW */ - FillFlags(); CPU_VERW(inst_op1_d); goto nextopcode; /* Else value will saved */ default: @@ -417,21 +407,13 @@ switch (inst.code.op) { case O_GRP7d: switch (inst.rm_index) { case 0: /* SGDT */ - { - Bitu limit,base; - CPU_SGDT(limit,base); - SaveMw(inst.rm_eaa,limit); - SaveMd(inst.rm_eaa+2,base); - goto nextopcode; - } + SaveMw(inst.rm_eaa,CPU_SGDT_limit()); + SaveMd(inst.rm_eaa+2,CPU_SGDT_base()); + goto nextopcode; case 1: /* SIDT */ - { - Bitu limit,base; - CPU_SIDT(limit,base); - SaveMw(inst.rm_eaa,limit); - SaveMd(inst.rm_eaa+2,base); - goto nextopcode; - } + SaveMw(inst.rm_eaa,CPU_SIDT_limit()); + SaveMd(inst.rm_eaa+2,CPU_SIDT_base()); + goto nextopcode; case 2: /* LGDT */ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); CPU_LGDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); @@ -441,11 +423,8 @@ switch (inst.code.op) { CPU_LIDT(LoadMw(inst.rm_eaa),LoadMd(inst.rm_eaa+2)&((inst.code.op == O_GRP7w) ? 0xFFFFFF : 0xFFFFFFFF)); goto nextopcode; case 4: /* SMSW */ - { - Bitu word;CPU_SMSW(word); - inst_op1_d=word; - break; - } + inst_op1_d=CPU_SMSW(); + break; case 6: /* LMSW */ FillFlags(); if (CPU_LMSW(inst_op1_w)) RunException(); @@ -481,7 +460,6 @@ switch (inst.code.op) { case O_LAR: { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - FillFlags(); Bitu ar=inst_op2_d; CPU_LAR(inst_op1_w,ar); inst_op1_d=(Bit32u)ar; @@ -490,7 +468,6 @@ switch (inst.code.op) { case O_LSL: { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegalopcode; - FillFlags(); Bitu limit=inst_op2_d; CPU_LSL(inst_op1_w,limit); inst_op1_d=(Bit32u)limit; @@ -499,7 +476,6 @@ switch (inst.code.op) { case O_ARPL: { if ((reg_flags & FLAG_VM) || !cpu.pmode) goto illegalopcode; - FillFlags(); Bitu new_sel=inst_op1_d; CPU_ARPL(new_sel,inst_op2_d); inst_op1_d=(Bit32u)new_sel; diff --git a/src/cpu/core_normal/prefix_0f.h b/src/cpu/core_normal/prefix_0f.h index 5924437..0f22983 100644 --- a/src/cpu/core_normal/prefix_0f.h +++ b/src/cpu/core_normal/prefix_0f.h @@ -25,15 +25,14 @@ case 0x01: /* STR */ { Bitu saveval; - if (!which) CPU_SLDT(saveval); - else CPU_STR(saveval); + if (!which) saveval=CPU_SLDT(); + else saveval=CPU_STR(); if (rm >= 0xc0) {GetEArw;*earw=saveval;} else {GetEAa;SaveMw(eaa,saveval);} } break; case 0x02:case 0x03:case 0x04:case 0x05: { - FillFlags(); Bitu loadval; if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} else {GetEAa;loadval=LoadMw(eaa);} @@ -64,17 +63,15 @@ { GetRM;Bitu which=(rm>>3)&7; if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit,base; + GetEAa;Bitu limit; switch (which) { case 0x00: /* SGDT */ - CPU_SGDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); + SaveMw(eaa,CPU_SGDT_limit()); + SaveMd(eaa+2,CPU_SGDT_base()); break; case 0x01: /* SIDT */ - CPU_SIDT(limit,base); - SaveMw(eaa,limit); - SaveMd(eaa+2,base); + SaveMw(eaa,CPU_SIDT_limit()); + SaveMd(eaa+2,CPU_SIDT_base()); break; case 0x02: /* LGDT */ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); @@ -85,8 +82,7 @@ CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2) & 0xFFFFFF); break; case 0x04: /* SMSW */ - CPU_SMSW(limit); - SaveMw(eaa,limit); + SaveMw(eaa,CPU_SMSW()); break; case 0x06: /* LMSW */ limit=LoadMw(eaa); @@ -98,7 +94,7 @@ break; } } else { - GetEArw;Bitu limit; + GetEArw; switch (which) { case 0x02: /* LGDT */ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); @@ -107,8 +103,7 @@ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); goto illegal_opcode; case 0x04: /* SMSW */ - CPU_SMSW(limit); - *earw=limit; + *earw=CPU_SMSW(); break; case 0x06: /* LMSW */ if (CPU_LMSW(*earw)) RUNEXCEPTION(); @@ -122,7 +117,6 @@ CASE_0F_W(0x02) /* LAR Gw,Ew */ { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrw;Bitu ar=*rmrw; if (rm >= 0xc0) { GetEArw;CPU_LAR(*earw,ar); @@ -135,7 +129,6 @@ CASE_0F_W(0x03) /* LSL Gw,Ew */ { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrw;Bitu limit=*rmrw; if (rm >= 0xc0) { GetEArw;CPU_LSL(*earw,limit); @@ -155,7 +148,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%d with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which); } GetEArd; Bit32u crx_value; @@ -169,7 +162,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR% with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV XXX,DR%u with non-register",which); } GetEArd; Bit32u drx_value; @@ -183,7 +176,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR% with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV XXX,CR%u with non-register",which); } GetEArd; if (CPU_WRITE_CRX(which,*eard)) RUNEXCEPTION(); @@ -195,7 +188,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV DR%,XXX with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV DR%u,XXX with non-register",which); } GetEArd; if (CPU_WRITE_DRX(which,*eard)) RUNEXCEPTION(); @@ -207,7 +200,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR% with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV XXX,TR%u with non-register",which); } GetEArd; Bit32u trx_value; @@ -221,7 +214,7 @@ Bitu which=(rm >> 3) & 7; if (rm < 0xc0 ) { rm |= 0xc0; - LOG(LOG_CPU,LOG_ERROR)("MOV TR%,XXX with non-register",which); + LOG(LOG_CPU,LOG_ERROR)("MOV TR%u,XXX with non-register",which); } GetEArd; if (CPU_WRITE_TRX(which,*eard)) RUNEXCEPTION(); diff --git a/src/cpu/core_normal/prefix_66.h b/src/cpu/core_normal/prefix_66.h index a76e43f..f2aef29 100644 --- a/src/cpu/core_normal/prefix_66.h +++ b/src/cpu/core_normal/prefix_66.h @@ -170,7 +170,6 @@ CASE_D(0x63) /* ARPL Ed,Rd */ { if (((cpu.pmode) && (reg_flags & FLAG_VM)) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrw; if (rm >= 0xc0 ) { GetEArd;Bitu new_sel=(Bit16u)*eard; @@ -398,12 +397,10 @@ continue; } CASE_D(0x9c) /* PUSHFD */ - FillFlags(); if (CPU_PUSHF(true)) RUNEXCEPTION(); break; CASE_D(0x9d) /* POPFD */ if (CPU_POPF(true)) RUNEXCEPTION(); - lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -511,7 +508,6 @@ } CASE_D(0xcf) /* IRET */ { - FillFlags(); CPU_IRET(true,GETIP); #if CPU_TRAP_CHECK if (GETFLAG(TF)) { diff --git a/src/cpu/core_normal/prefix_66_0f.h b/src/cpu/core_normal/prefix_66_0f.h index 3022ba5..8c00c26 100644 --- a/src/cpu/core_normal/prefix_66_0f.h +++ b/src/cpu/core_normal/prefix_66_0f.h @@ -25,8 +25,8 @@ case 0x01: /* STR */ { Bitu saveval; - if (!which) CPU_SLDT(saveval); - else CPU_STR(saveval); + if (!which) saveval=CPU_SLDT(); + else saveval=CPU_STR(); if (rm >= 0xc0) {GetEArw;*earw=(Bit16u)saveval;} else {GetEAa;SaveMw(eaa,saveval);} } @@ -34,7 +34,6 @@ case 0x02:case 0x03:case 0x04:case 0x05: { /* Just use 16-bit loads since were only using selectors */ - FillFlags(); Bitu loadval; if (rm >= 0xc0 ) {GetEArw;loadval=*earw;} else {GetEAa;loadval=LoadMw(eaa);} @@ -66,17 +65,15 @@ { GetRM;Bitu which=(rm>>3)&7; if (rm < 0xc0) { //First ones all use EA - GetEAa;Bitu limit,base; + GetEAa;Bitu limit; switch (which) { case 0x00: /* SGDT */ - CPU_SGDT(limit,base); - SaveMw(eaa,(Bit16u)limit); - SaveMd(eaa+2,(Bit32u)base); + SaveMw(eaa,(Bit16u)CPU_SGDT_limit()); + SaveMd(eaa+2,(Bit32u)CPU_SGDT_base()); break; case 0x01: /* SIDT */ - CPU_SIDT(limit,base); - SaveMw(eaa,(Bit16u)limit); - SaveMd(eaa+2,(Bit32u)base); + SaveMw(eaa,(Bit16u)CPU_SIDT_limit()); + SaveMd(eaa+2,(Bit32u)CPU_SIDT_base()); break; case 0x02: /* LGDT */ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); @@ -87,8 +84,7 @@ CPU_LIDT(LoadMw(eaa),LoadMd(eaa+2)); break; case 0x04: /* SMSW */ - CPU_SMSW(limit); - SaveMw(eaa,(Bit16u)limit); + SaveMw(eaa,(Bit16u)CPU_SMSW()); break; case 0x06: /* LMSW */ limit=LoadMw(eaa); @@ -100,7 +96,7 @@ break; } } else { - GetEArd;Bitu limit; + GetEArd; switch (which) { case 0x02: /* LGDT */ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); @@ -109,8 +105,7 @@ if (cpu.pmode && cpu.cpl) EXCEPTION(EXCEPTION_GP); goto illegal_opcode; case 0x04: /* SMSW */ - CPU_SMSW(limit); - *eard=(Bit32u)limit; + *eard=(Bit32u)CPU_SMSW(); break; case 0x06: /* LMSW */ if (CPU_LMSW(*eard)) RUNEXCEPTION(); @@ -127,7 +122,6 @@ CASE_0F_D(0x02) /* LAR Gd,Ed */ { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrd;Bitu ar=*rmrd; if (rm >= 0xc0) { GetEArw;CPU_LAR(*earw,ar); @@ -140,7 +134,6 @@ CASE_0F_D(0x03) /* LSL Gd,Ew */ { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrd;Bitu limit=*rmrd; /* Just load 16-bit values for selectors */ if (rm >= 0xc0) { diff --git a/src/cpu/core_normal/prefix_none.h b/src/cpu/core_normal/prefix_none.h index 36739a3..9622294 100644 --- a/src/cpu/core_normal/prefix_none.h +++ b/src/cpu/core_normal/prefix_none.h @@ -239,7 +239,6 @@ CASE_W(0x63) /* ARPL Ew,Rw */ { if ((reg_flags & FLAG_VM) || (!cpu.pmode)) goto illegal_opcode; - FillFlags(); GetRMrw; if (rm >= 0xc0 ) { GetEArw;Bitu new_sel=*earw; @@ -574,12 +573,10 @@ CASE_B(0x9b) /* WAIT */ break; /* No waiting here */ CASE_W(0x9c) /* PUSHF */ - FillFlags(); if (CPU_PUSHF(false)) RUNEXCEPTION(); break; CASE_W(0x9d) /* POPF */ if (CPU_POPF(false)) RUNEXCEPTION(); - lflags.type=t_UNKNOWN; #if CPU_TRAP_CHECK if (GETFLAG(TF)) { cpudecoder=CPU_Core_Normal_Trap_Run; @@ -740,8 +737,8 @@ CPU_RET(false,0,GETIP); continue; CASE_B(0xcc) /* INT3 */ - FillFlags(); #if C_DEBUG + FillFlags(); if (DEBUG_Breakpoint()) return debugCallback; #endif @@ -753,8 +750,8 @@ CASE_B(0xcd) /* INT Ib */ { Bit8u num=Fetchb(); - FillFlags(); #if C_DEBUG + FillFlags(); if (DEBUG_IntBreakpoint(num)) { return debugCallback; } @@ -767,7 +764,6 @@ } CASE_B(0xce) /* INTO */ if (get_OF()) { - FillFlags(); CPU_SW_Interrupt(4,GETIP); #if CPU_TRAP_CHECK cpu.trap_skip=true; @@ -777,7 +773,6 @@ break; CASE_W(0xcf) /* IRET */ { - FillFlags(); CPU_IRET(false,GETIP); #if CPU_TRAP_CHECK if (GETFLAG(TF)) { @@ -953,7 +948,6 @@ LOG(LOG_CPU,LOG_NORMAL)("CPU:LOCK"); /* FIXME: see case D_LOCK in core_full/load.h */ break; CASE_B(0xf1) /* ICEBP */ - FillFlags(); CPU_SW_Interrupt_NoIOPLCheck(1,GETIP); #if CPU_TRAP_CHECK cpu.trap_skip=true; diff --git a/src/cpu/core_normal/support.h b/src/cpu/core_normal/support.h index 8a78955..65dbfa3 100644 --- a/src/cpu/core_normal/support.h +++ b/src/cpu/core_normal/support.h @@ -42,7 +42,6 @@ static INLINE Bit32s Fetchds() { #define RUNEXCEPTION() { \ - FillFlags(); \ CPU_Exception(cpu.exception.which,cpu.exception.error); \ continue; \ } diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index b38ccb5..7d6b5a8 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cpu.cpp,v 1.98 2007/02/22 08:35:34 qbix79 Exp $ */ +/* $Id: cpu.cpp,v 1.102 2007/06/12 20:22:07 c2woody Exp $ */ #include #include @@ -27,6 +27,7 @@ #include "mapper.h" #include "setup.h" #include "paging.h" +#include "lazyflags.h" #include "support.h" Bitu DEBUG_EnableDebugger(void); @@ -62,10 +63,16 @@ Bitu CPU_AutoDetermineMode; void CPU_Core_Full_Init(void); void CPU_Core_Normal_Init(void); void CPU_Core_Simple_Init(void); +#if (C_DYNAMIC_X86) void CPU_Core_Dyn_X86_Init(void); void CPU_Core_Dyn_X86_Cache_Init(bool enable_cache); void CPU_Core_Dyn_X86_Cache_Close(void); void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); +#elif (C_DYNREC) +void CPU_Core_Dynrec_Init(void); +void CPU_Core_Dynrec_Cache_Init(bool enable_cache); +void CPU_Core_Dynrec_Cache_Close(void); +#endif /* In debug mode exceptions are tested and dosbox exits when * a unhandled exception state is detected. @@ -87,7 +94,7 @@ void CPU_Core_Dyn_X86_SetFPUMode(bool dh_fpu); #if defined(CPU_CHECK_IGNORE) #define CPU_CHECK_COND(cond,msg,exc,sel) { \ - cond; \ + if (cond) do {} while (0); \ } #elif defined(CPU_CHECK_EXCEPT) #define CPU_CHECK_COND(cond,msg,exc,sel) { \ @@ -178,6 +185,7 @@ bool CPU_POPF(Bitu use32) { if (use32) CPU_SetFlags(CPU_Pop32(),mask); else CPU_SetFlags(CPU_Pop16(),mask & 0xffff); + DestroyConditionFlags(); return false; } @@ -186,6 +194,7 @@ bool CPU_PUSHF(Bitu use32) { /* Not enough privileges to execute PUSHF */ return CPU_PrepareException(EXCEPTION_GP,0); } + FillFlags(); if (use32) CPU_Push32(reg_flags & 0xfcffff); else CPU_Push16(reg_flags); @@ -258,6 +267,7 @@ enum TSwitchType { }; bool CPU_SwitchTask(Bitu new_tss_selector,TSwitchType tstype,Bitu old_eip) { + FillFlags(); TaskStateSegment new_tss; if (!new_tss.SetSelector(new_tss_selector)) E_Exit("Illegal TSS for switch, selector=%x, switchtype=%x",new_tss_selector,tstype); @@ -447,6 +457,7 @@ void CPU_Exception(Bitu which,Bitu error ) { Bit8u lastint; void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { lastint=num; + FillFlags(); #if C_DEBUG switch (num) { case 0xcd: @@ -666,6 +677,7 @@ void CPU_IRET(bool use32,Bitu oldeip) { CPU_SetFlags(CPU_Pop16(),FMASK_ALL & 0xffff); } cpu.code.big=false; + DestroyConditionFlags(); return; } else { /* Protected mode IRET */ if (reg_flags & FLAG_VM) { @@ -686,6 +698,7 @@ void CPU_IRET(bool use32,Bitu oldeip) { CPU_SetFlags(CPU_Pop16(),FMASK_NORMAL|FLAG_NT); } cpu.code.big=false; + DestroyConditionFlags(); return; } } @@ -717,6 +730,7 @@ void CPU_IRET(bool use32,Bitu oldeip) { n_gs=CPU_Pop32() & 0xffff; CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM); + DestroyConditionFlags(); cpu.cpl=3; CPU_SetSegGeneral(ss,n_ss); @@ -779,6 +793,7 @@ void CPU_IRET(bool use32,Bitu oldeip) { Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL; if (GETFLAG_IOPL0)) return CPU_PrepareException(EXCEPTION_GP,0); word&=0xf; if (cpu.cr0 & 1) word|=1; @@ -1624,6 +1644,7 @@ Bitu CPU_LMSW(Bitu word) { } void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { + FillFlags(); if ((dest_sel & 3) < (src_sel & 3)) { dest_sel=(dest_sel & 0xfffc) + (src_sel & 3); // dest_sel|=0xff3f0000; @@ -1634,6 +1655,7 @@ void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { } void CPU_LAR(Bitu selector,Bitu & ar) { + FillFlags(); if (selector == 0) { SETFLAGBIT(ZF,false); return; @@ -1685,6 +1707,7 @@ void CPU_LAR(Bitu selector,Bitu & ar) { } void CPU_LSL(Bitu selector,Bitu & limit) { + FillFlags(); if (selector == 0) { SETFLAGBIT(ZF,false); return; @@ -1727,6 +1750,7 @@ void CPU_LSL(Bitu selector,Bitu & limit) { } void CPU_VERR(Bitu selector) { + FillFlags(); if (selector == 0) { SETFLAGBIT(ZF,false); return; @@ -1759,6 +1783,7 @@ void CPU_VERR(Bitu selector) { } void CPU_VERW(Bitu selector) { + FillFlags(); if (selector == 0) { SETFLAGBIT(ZF,false); return; @@ -2050,6 +2075,8 @@ public: CPU_Core_Full_Init(); #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Init(); +#elif (C_DYNREC) + CPU_Core_Dynrec_Init(); #endif MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles"); MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles"); @@ -2153,6 +2180,10 @@ public: cpudecoder=&CPU_Core_Normal_Run; CPU_AutoDetermineMode|=CPU_AUTODETERMINE_CORE; } +#elif (C_DYNREC) + else if (!strcasecmp(core,"dynamic")) { + cpudecoder=&CPU_Core_Dynrec_Run; + } #endif else { LOG_MSG("CPU:Unknown core type %s, switching back to normal.",core); @@ -2160,6 +2191,8 @@ public: #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Cache_Init(!strcasecmp(core,"dynamic") || !strcasecmp(core,"dynamic_nodhfpu")); +#elif (C_DYNREC) + CPU_Core_Dynrec_Cache_Init(!strcasecmp(core,"dynamic")); #endif if(CPU_CycleMax <= 0) CPU_CycleMax = 3000; @@ -2177,6 +2210,8 @@ static CPU * test; void CPU_ShutDown(Section* sec) { #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Cache_Close(); +#elif (C_DYNREC) + CPU_Core_Dynrec_Cache_Close(); #endif delete test; } diff --git a/src/cpu/flags.cpp b/src/cpu/flags.cpp index b683020..d475dfe 100644 --- a/src/cpu/flags.cpp +++ b/src/cpu/flags.cpp @@ -31,7 +31,7 @@ LazyFlags lflags; /* CF Carry Flag -- Set on high-order bit carry or borrow; cleared otherwise. */ -Bitu get_CF(void) { +Bit32u get_CF(void) { switch (lflags.type) { case t_UNKNOWN: @@ -43,7 +43,6 @@ Bitu get_CF(void) { case t_DECd: case t_MUL: return GETFLAG(CF); - break; case t_ADDb: return (lf_resb 0x80); + else return false; + case t_SHRw: + if ((lf_var2b&0x1f)==1) return (lf_var1w > 0x8000); + else return false; + case t_SHRd: + if ((lf_var2b&0x1f)==1) return (lf_var1d > 0x80000000); + else return false; case t_ORb: case t_ORw: case t_ORd: @@ -442,14 +450,14 @@ Bit16u parity_lookup[256] = { FLAG_PF, 0, 0, FLAG_PF, 0, FLAG_PF, FLAG_PF, 0, 0, FLAG_PF, FLAG_PF, 0, FLAG_PF, 0, 0, FLAG_PF }; -Bitu get_PF(void) { +Bit32u get_PF(void) { switch (lflags.type) { case t_UNKNOWN: return GETFLAG(PF); default: - return (parity_lookup[lf_resb]);; + return (parity_lookup[lf_resb]); }; - return false; + return 0; } @@ -486,6 +494,7 @@ Bitu FillFlags(void) { #define SETCF(NEWBIT) reg_flags=(reg_flags & ~FLAG_CF)|(NEWBIT); #define SET_FLAG SETFLAGBIT + Bitu FillFlags(void) { switch (lflags.type) { case t_UNKNOWN: @@ -683,6 +692,7 @@ Bitu FillFlags(void) { DOFLAG_SFb; SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SHLw: if (lf_var2b>16) SET_FLAG(CF,false); @@ -691,6 +701,7 @@ Bitu FillFlags(void) { DOFLAG_SFw; SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SHLd: SET_FLAG(CF,(lf_var1d >> (32 - lf_var2b)) & 1); @@ -698,6 +709,7 @@ Bitu FillFlags(void) { DOFLAG_SFd; SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; @@ -721,22 +733,28 @@ Bitu FillFlags(void) { SET_FLAG(CF,(lf_var1b >> (lf_var2b - 1)) & 1); DOFLAG_ZFb; DOFLAG_SFb; - SET_FLAG(OF,(lf_resb ^ lf_var1b) & 0x80); + if ((lf_var2b&0x1f)==1) SET_FLAG(OF,(lf_var1b >= 0x80)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SHRw: SET_FLAG(CF,(lf_var1w >> (lf_var2b - 1)) & 1); DOFLAG_ZFw; DOFLAG_SFw; - SET_FLAG(OF,(lf_resw ^ lf_var1w) & 0x8000); + if ((lf_var2w&0x1f)==1) SET_FLAG(OF,(lf_var1w >= 0x8000)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SHRd: SET_FLAG(CF,(lf_var1d >> (lf_var2b - 1)) & 1); DOFLAG_ZFd; DOFLAG_SFd; - SET_FLAG(OF,(lf_resd ^ lf_var1d) & 0x80000000); + if ((lf_var2d&0x1f)==1) SET_FLAG(OF,(lf_var1d >= 0x80000000)); + else SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; @@ -762,6 +780,7 @@ Bitu FillFlags(void) { DOFLAG_SFb; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); break; case t_SARw: SET_FLAG(CF,(((Bit16s) lf_var1w) >> (lf_var2b - 1)) & 1); @@ -769,6 +788,7 @@ Bitu FillFlags(void) { DOFLAG_SFw; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); break; case t_SARd: SET_FLAG(CF,(((Bit32s) lf_var1d) >> (lf_var2b - 1)) & 1); @@ -776,6 +796,7 @@ Bitu FillFlags(void) { DOFLAG_SFd; SET_FLAG(OF,false); DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); break; case t_INCb: @@ -860,4 +881,308 @@ Bitu FillFlags(void) { return reg_flags; } +void FillFlagsNoCFOF(void) { + switch (lflags.type) { + case t_UNKNOWN: + return; + case t_ADDb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ADDw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ADDd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + case t_ADCb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ADCw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ADCd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SBBb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_SBBw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_SBBd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SUBb: + case t_CMPb: + DOFLAG_AF; + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_SUBw: + case t_CMPw: + DOFLAG_AF; + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_SUBd: + case t_CMPd: + DOFLAG_AF; + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_ORb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_ORw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_ORd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_TESTb: + case t_ANDb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_TESTw: + case t_ANDw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_TESTd: + case t_ANDd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_XORb: + SET_FLAG(AF,false); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_XORw: + SET_FLAG(AF,false); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_XORd: + SET_FLAG(AF,false); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SHLb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SHLw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SHLd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + + case t_DSHLw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DSHLd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SHRb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SHRw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SHRd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + + case t_DSHRw: /* Hmm this is not correct for shift higher than 16 */ + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DSHRd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_SARb: + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2b&0x1f)); + break; + case t_SARw: + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2w&0x1f)); + break; + case t_SARd: + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + SET_FLAG(AF,(lf_var2d&0x1f)); + break; + + case t_INCb: + SET_FLAG(AF,(lf_resb & 0x0f) == 0); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_INCw: + SET_FLAG(AF,(lf_resw & 0x0f) == 0); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_INCd: + SET_FLAG(AF,(lf_resd & 0x0f) == 0); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + case t_DECb: + SET_FLAG(AF,(lf_resb & 0x0f) == 0x0f); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_DECw: + SET_FLAG(AF,(lf_resw & 0x0f) == 0x0f); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_DECd: + SET_FLAG(AF,(lf_resd & 0x0f) == 0x0f); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + case t_NEGb: + SET_FLAG(AF,(lf_resb & 0x0f) != 0); + DOFLAG_ZFb; + DOFLAG_SFb; + DOFLAG_PF; + break; + case t_NEGw: + SET_FLAG(AF,(lf_resw & 0x0f) != 0); + DOFLAG_ZFw; + DOFLAG_SFw; + DOFLAG_PF; + break; + case t_NEGd: + SET_FLAG(AF,(lf_resd & 0x0f) != 0); + DOFLAG_ZFd; + DOFLAG_SFd; + DOFLAG_PF; + break; + + + case t_DIV: + case t_MUL: + break; + + default: + LOG(LOG_CPU,LOG_ERROR)("Unhandled flag type %d",lflags.type); + break; + } + lflags.type=t_UNKNOWN; +} + +void DestroyConditionFlags(void) { + lflags.type=t_UNKNOWN; +} + #endif diff --git a/src/cpu/instructions.h b/src/cpu/instructions.h index 5f3505b..45b2c79 100644 --- a/src/cpu/instructions.h +++ b/src/cpu/instructions.h @@ -230,13 +230,13 @@ #define ROLB(op1,op2,load,save) \ if (!(op2&0x7)) { \ if (op2&0x18) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1 & 1); \ SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 7)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1b=load(op1); \ lf_var2b=op2&0x07; \ lf_resb=(lf_var1b << lf_var2b) | \ @@ -248,12 +248,13 @@ #define ROLW(op1,op2,load,save) \ if (!(op2&0xf)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1 & 1); \ + SETFLAGBIT(OF,(op1 & 1) ^ (op1 >> 15)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1w=load(op1); \ lf_var2b=op2&0xf; \ lf_resw=(lf_var1w << lf_var2b) | \ @@ -264,7 +265,7 @@ #define ROLD(op1,op2,load,save) \ if (!op2) break; \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1d=load(op1); \ lf_var2b=op2; \ lf_resd=(lf_var1d << lf_var2b) | \ @@ -277,48 +278,49 @@ #define RORB(op1,op2,load,save) \ if (!(op2&0x7)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1>>7); \ SETFLAGBIT(OF,(op1>>7) ^ ((op1>>6) & 1)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1b=load(op1); \ lf_var2b=op2&0x07; \ lf_resb=(lf_var1b >> lf_var2b) | \ (lf_var1b << (8-lf_var2b)); \ save(op1,lf_resb); \ SETFLAGBIT(CF,lf_resb & 0x80); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); #define RORW(op1,op2,load,save) \ if (!(op2&0xf)) { \ if (op2&0x10) { \ - FillFlags(); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(CF,op1>>15); \ + SETFLAGBIT(OF,(op1>>15) ^ ((op1>>14) & 1)); \ } \ break; \ } \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1w=load(op1); \ lf_var2b=op2&0xf; \ lf_resw=(lf_var1w >> lf_var2b) | \ (lf_var1w << (16-lf_var2b)); \ save(op1,lf_resw); \ SETFLAGBIT(CF,lf_resw & 0x8000); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); #define RORD(op1,op2,load,save) \ if (!op2) break; \ - FillFlags(); \ + FillFlagsNoCFOF(); \ lf_var1d=load(op1); \ lf_var2b=op2; \ lf_resd=(lf_var1d >> lf_var2b) | \ (lf_var1d << (32-lf_var2b)); \ save(op1,lf_resd); \ SETFLAGBIT(CF,lf_resd & 0x80000000); \ - if (lf_var2b == 1) SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); #define RCLB(op1,op2,load,save) \ @@ -376,7 +378,7 @@ (lf_var1b << (9-lf_var2b)); \ save(op1,lf_resb); \ SETFLAGBIT(CF,(lf_var1b >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resb ^ lf_var1b) & 0x80); \ + SETFLAGBIT(OF,(lf_resb ^ (lf_resb<<1)) & 0x80); \ } #define RCRW(op1,op2,load,save) \ @@ -389,7 +391,7 @@ (lf_var1w << (17-lf_var2b)); \ save(op1,lf_resw); \ SETFLAGBIT(CF,(lf_var1w >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resw ^ lf_var1w) & 0x8000); \ + SETFLAGBIT(OF,(lf_resw ^ (lf_resw<<1)) & 0x8000); \ } #define RCRD(op1,op2,load,save) \ @@ -406,7 +408,7 @@ } \ save(op1,lf_resd); \ SETFLAGBIT(CF,(lf_var1d >> (lf_var2b - 1)) & 1); \ - SETFLAGBIT(OF,(lf_resd ^ lf_var1d) & 0x80000000); \ + SETFLAGBIT(OF,(lf_resd ^ (lf_resd<<1)) & 0x80000000); \ } @@ -520,12 +522,14 @@ #define DAS() \ +{ \ + Bit8u osigned=reg_al & 0x80; \ if (((reg_al & 0x0f) > 9) || get_AF()) { \ if ((reg_al>0x99) || get_CF()) { \ reg_al-=0x60; \ SETFLAGBIT(CF,true); \ } else { \ - SETFLAGBIT(CF,false); \ + SETFLAGBIT(CF,(reg_al<=0x05)); \ } \ reg_al-=6; \ SETFLAGBIT(AF,true); \ @@ -538,44 +542,61 @@ } \ SETFLAGBIT(AF,false); \ } \ + SETFLAGBIT(OF,osigned && ((reg_al&0x80)==0)); \ SETFLAGBIT(SF,(reg_al&0x80)); \ SETFLAGBIT(ZF,(reg_al==0)); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ - lflags.type=t_UNKNOWN; + lflags.type=t_UNKNOWN; \ +} #define AAA() \ - if (get_AF() || ((reg_al & 0xf) > 9)) \ - { \ + SETFLAGBIT(SF,((reg_al>=0x7a) && (reg_al<=0xf9))); \ + if ((reg_al & 0xf) > 9) { \ + SETFLAGBIT(OF,(reg_al&0xf0)==0x70); \ reg_ax += 0x106; \ - SETFLAGBIT(AF,true); \ SETFLAGBIT(CF,true); \ + SETFLAGBIT(ZF,(reg_al == 0)); \ + SETFLAGBIT(AF,true); \ + } else if (get_AF()) { \ + reg_ax += 0x106; \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(CF,true); \ + SETFLAGBIT(ZF,false); \ + SETFLAGBIT(AF,true); \ } else { \ - SETFLAGBIT(AF,false); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false); \ + SETFLAGBIT(ZF,(reg_al == 0)); \ + SETFLAGBIT(AF,false); \ } \ + SETFLAGBIT(PF,parity_lookup[reg_al]); \ reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; \ - SETFLAGBIT(SF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); + lflags.type=t_UNKNOWN; #define AAS() \ - if (((reg_al & 0x0f)>9) || get_AF()) { \ + if ((reg_al & 0x0f)>9) { \ + SETFLAGBIT(SF,(reg_al>0x85)); \ reg_ax -= 0x106; \ - SETFLAGBIT(AF,true); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,true); \ + SETFLAGBIT(AF,true); \ + } else if (get_AF()) { \ + SETFLAGBIT(OF,((reg_al>=0x80) && (reg_al<=0x85))); \ + SETFLAGBIT(SF,(reg_al<0x06) || (reg_al>0x85)); \ + reg_ax -= 0x106; \ + SETFLAGBIT(CF,true); \ + SETFLAGBIT(AF,true); \ } else { \ - SETFLAGBIT(AF,false); \ + SETFLAGBIT(SF,(reg_al>=0x80)); \ + SETFLAGBIT(OF,false); \ SETFLAGBIT(CF,false); \ + SETFLAGBIT(AF,false); \ } \ - reg_al &= 0x0F; \ - lflags.type=t_UNKNOWN; \ - SETFLAGBIT(SF,0); \ - SETFLAGBIT(OF,0); \ SETFLAGBIT(ZF,(reg_al == 0)); \ - SETFLAGBIT(PF,parity_lookup[reg_al]); + SETFLAGBIT(PF,parity_lookup[reg_al]); \ + reg_al &= 0x0F; \ + lflags.type=t_UNKNOWN; #define AAM(op1) \ { \ @@ -586,9 +607,9 @@ SETFLAGBIT(SF,(reg_al & 0x80)); \ SETFLAGBIT(ZF,(reg_al == 0)); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ - SETFLAGBIT(CF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(AF,0); \ + SETFLAGBIT(CF,false); \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(AF,false); \ lflags.type=t_UNKNOWN; \ } else EXCEPTION(0); \ } @@ -601,9 +622,9 @@ Bit16u ax2 = ax1 + reg_al; \ reg_al = (Bit8u) ax2; \ reg_ah = 0; \ - SETFLAGBIT(CF,0); \ - SETFLAGBIT(OF,0); \ - SETFLAGBIT(AF,0); \ + SETFLAGBIT(CF,false); \ + SETFLAGBIT(OF,false); \ + SETFLAGBIT(AF,false); \ SETFLAGBIT(SF,reg_al >= 0x80); \ SETFLAGBIT(ZF,reg_al == 0); \ SETFLAGBIT(PF,parity_lookup[reg_al]); \ @@ -611,8 +632,8 @@ } #define MULB(op1,load,save) \ - FillFlags(); \ reg_ax=reg_al*load(op1); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_al == 0); \ if (reg_ax & 0xff00) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -622,10 +643,10 @@ #define MULW(op1,load,save) \ { \ - FillFlags(); \ Bitu tempu=(Bitu)reg_ax*(Bitu)(load(op1)); \ reg_ax=(Bit16u)(tempu); \ reg_dx=(Bit16u)(tempu >> 16); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_ax == 0); \ if (reg_dx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -636,10 +657,10 @@ #define MULD(op1,load,save) \ { \ - FillFlags(); \ Bit64u tempu=(Bit64u)reg_eax*(Bit64u)(load(op1)); \ reg_eax=(Bit32u)(tempu); \ reg_edx=(Bit32u)(tempu >> 32); \ + FillFlagsNoCFOF(); \ SETFLAGBIT(ZF,reg_eax == 0); \ if (reg_edx) { \ SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \ @@ -729,8 +750,8 @@ #define IMULB(op1,load,save) \ { \ - FillFlags(); \ reg_ax=((Bit8s)reg_al) * ((Bit8s)(load(op1))); \ + FillFlagsNoCFOF(); \ if ((reg_ax & 0xff80)==0xff80 || \ (reg_ax & 0xff80)==0x0000) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -742,10 +763,10 @@ #define IMULW(op1,load,save) \ { \ - FillFlags(); \ Bits temps=((Bit16s)reg_ax)*((Bit16s)(load(op1))); \ reg_ax=(Bit16s)(temps); \ reg_dx=(Bit16s)(temps >> 16); \ + FillFlagsNoCFOF(); \ if (((temps & 0xffff8000)==0xffff8000 || \ (temps & 0xffff8000)==0x0000)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -756,11 +777,11 @@ #define IMULD(op1,load,save) \ { \ - FillFlags(); \ Bit64s temps=((Bit64s)((Bit32s)reg_eax))* \ ((Bit64s)((Bit32s)(load(op1)))); \ reg_eax=(Bit32u)(temps); \ reg_edx=(Bit32u)(temps >> 32); \ + FillFlagsNoCFOF(); \ if ((reg_edx==0xffffffff) && \ (reg_eax & 0x80000000) ) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ @@ -774,10 +795,9 @@ #define DIMULW(op1,op2,op3,load,save) \ { \ - FillFlags(); \ - Bits res; \ - res=((Bit16s)op2) * ((Bit16s)op3); \ + Bits res=((Bit16s)op2) * ((Bit16s)op3); \ save(op1,res & 0xffff); \ + FillFlagsNoCFOF(); \ if ((res> -32768) && (res<32767)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ } else { \ @@ -787,9 +807,9 @@ #define DIMULD(op1,op2,op3,load,save) \ { \ - FillFlags(); \ Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \ save(op1,(Bit32s)res); \ + FillFlagsNoCFOF(); \ if ((res>-((Bit64s)(2147483647)+1)) && \ (res<(Bit64s)2147483647)) { \ SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \ diff --git a/src/cpu/lazyflags.h b/src/cpu/lazyflags.h index 0d93650..2f088ec 100644 --- a/src/cpu/lazyflags.h +++ b/src/cpu/lazyflags.h @@ -20,14 +20,16 @@ #define __LAZYFLAG_H //Flag Handling -Bitu get_CF(void); -Bitu get_AF(void); -Bitu get_ZF(void); -Bitu get_SF(void); -Bitu get_OF(void); -Bitu get_PF(void); +Bit32u get_CF(void); +Bit32u get_AF(void); +Bit32u get_ZF(void); +Bit32u get_SF(void); +Bit32u get_OF(void); +Bit32u get_PF(void); Bitu FillFlags(void); +void FillFlagsNoCFOF(void); +void DestroyConditionFlags(void); #include "regs.h" diff --git a/src/debug/debug.cpp b/src/debug/debug.cpp index 2f3f28e..d6ea47e 100644 --- a/src/debug/debug.cpp +++ b/src/debug/debug.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: debug.cpp,v 1.85 2007/02/25 18:38:00 c2woody Exp $ */ +/* $Id: debug.cpp,v 1.88 2007/06/12 20:22:07 c2woody Exp $ */ #include "dosbox.h" #if C_DEBUG @@ -755,7 +755,7 @@ static void DrawRegisters(void) { } wattrset(dbg.win_reg,0); - mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count); + mvwprintw(dbg.win_reg,3,60,"%u ",cycle_count); wrefresh(dbg.win_reg); }; @@ -805,7 +805,7 @@ static void DrawCode(void) line20[20 - drawsize*2] = ' '; } else waddstr(dbg.win_code,line20); - char* res = 0; + char* res = ""; if (showExtend) res = AnalyzeInstruction(dline, saveSel); // Spacepad it up to 28 characters size_t dline_len = strlen(dline); @@ -1776,13 +1776,12 @@ static void LogCPUInfo(void) sprintf(out1,"IDT base=%08X limit=%08X",cpu.idt.GetBase(),cpu.idt.GetLimit()); LOG(LOG_MISC,LOG_ERROR)(out1); - Bitu sel; + Bitu sel=CPU_STR(); Descriptor desc; - CPU_STR(sel); cpu.gdt.GetDescriptor(sel,desc); sprintf(out1,"TR selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1); LOG(LOG_MISC,LOG_ERROR)(out1); - sel=cpu.gdt.SLDT(); + sel=CPU_SLDT(); cpu.gdt.GetDescriptor(sel,desc); sprintf(out1,"LDT selector=%04X, base=%08X limit=%08X*%X",sel,desc.GetBase(),desc.GetLimit(),desc.saved.seg.g?0x4000:1); LOG(LOG_MISC,LOG_ERROR)(out1); @@ -2210,12 +2209,12 @@ void DEBUG_HeavyLogInstruction(void) { inst.s_fs = SegValue(fs); inst.s_gs = SegValue(gs); inst.s_ss = SegValue(ss); - inst.c = get_CF(); - inst.z = get_ZF(); - inst.s = get_SF(); - inst.o = get_OF(); - inst.a = get_AF(); - inst.p = get_PF(); + inst.c = get_CF()>0; + inst.z = get_ZF()>0; + inst.s = get_SF()>0; + inst.o = get_OF()>0; + inst.a = get_AF()>0; + inst.p = get_PF()>0; inst.i = GETFLAGBOOL(IF); if (++logCount >= LOGCPUMAX) logCount = 0; diff --git a/src/debug/debug_gui.cpp b/src/debug/debug_gui.cpp index aa0aeb3..2ee2217 100644 --- a/src/debug/debug_gui.cpp +++ b/src/debug/debug_gui.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: debug_gui.cpp,v 1.31 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: debug_gui.cpp,v 1.32 2007/05/09 14:35:51 c2woody Exp $ */ #include "dosbox.h" @@ -106,7 +106,7 @@ void LOG::operator() (char const* format, ...){ if (d_type>=LOG_MAX) return; if ((d_severity!=LOG_ERROR) && (!loggrp[d_type].enabled)) return; - DEBUG_ShowMsg("%10d: %s:%s\n",cycle_count,loggrp[d_type].front,buf); + DEBUG_ShowMsg("%10u: %s:%s\n",cycle_count,loggrp[d_type].front,buf); } @@ -250,6 +250,7 @@ void LOG_StartUp(void) { lowcase(buf); sect->Add_bool(buf,true); } + MSG_Add("LOG_CONFIGFILE_HELP","Logging related options for the debugger.\n"); } diff --git a/src/dos/cdrom.cpp b/src/dos/cdrom.cpp index ad92fea..3e13ac3 100644 --- a/src/dos/cdrom.cpp +++ b/src/dos/cdrom.cpp @@ -85,7 +85,7 @@ bool CDROM_Interface_SDL::GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) bool CDROM_Interface_SDL::GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) { if (CD_INDRIVE(SDL_CDStatus(cd))) { - FRAMES_TO_MSF(cd->track[track-1].offset+150,&start.min,&start.sec,&start.fr); + FRAMES_TO_MSF(cd->track[track-1].offset,&start.min,&start.sec,&start.fr); attr = cd->track[track-1].type<<4;//sdl uses 0 for audio and 4 for data. instead of 0x00 and 0x40 } return CD_INDRIVE(SDL_CDStatus(cd)); diff --git a/src/dos/cdrom.h b/src/dos/cdrom.h index 705f842..bad8406 100644 --- a/src/dos/cdrom.h +++ b/src/dos/cdrom.h @@ -76,7 +76,7 @@ public: virtual bool PlayAudioSector (unsigned long start,unsigned long len); virtual bool PauseAudio (bool resume); virtual bool StopAudio (void); - virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return false; }; + virtual bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; }; virtual bool LoadUnloadMedia (bool unload); private: @@ -91,18 +91,18 @@ private: class CDROM_Interface_Fake : public CDROM_Interface { public: - bool SetDevice (char* path, int forceCD) { return true; }; + bool SetDevice (char* /*path*/, int /*forceCD*/) { return true; }; bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; }; bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut); bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr); bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos); bool GetAudioStatus (bool& playing, bool& pause); bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen); - bool PlayAudioSector (unsigned long start,unsigned long len) { return true; }; - bool PauseAudio (bool resume) { return true; }; + bool PlayAudioSector (unsigned long /*start*/,unsigned long /*len*/) { return true; }; + bool PauseAudio (bool /*resume*/) { return true; }; bool StopAudio (void) { return true; }; - bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) { return true; }; - bool LoadUnloadMedia (bool unload) { return true; }; + bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return true; }; + bool LoadUnloadMedia (bool /*unload*/) { return true; }; }; class CDROM_Interface_Image : public CDROM_Interface @@ -112,6 +112,7 @@ private: public: virtual bool read(Bit8u *buffer, int seek, int count) = 0; virtual int getLength() = 0; + virtual ~TrackFile() { }; }; class BinaryFile : public TrackFile { diff --git a/src/dos/cdrom_aspi_win32.cpp b/src/dos/cdrom_aspi_win32.cpp index fcc0edb..1d8b888 100644 --- a/src/dos/cdrom_aspi_win32.cpp +++ b/src/dos/cdrom_aspi_win32.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cdrom_aspi_win32.cpp,v 1.17 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: cdrom_aspi_win32.cpp,v 1.18 2007/06/12 20:22:07 c2woody Exp $ */ #if defined (WIN32) @@ -148,7 +148,6 @@ bool CDROM_Interface_Aspi::ScanRegistryFindKey(HKEY& hKeyBase) ULONG result,newKeyResult; char subKey[256]; char buffer[256]; - ULONG bufferSize = 256; ULONG subKeySize = 256; HKEY hNewKey; @@ -596,7 +595,6 @@ bool CDROM_Interface_Aspi::GetUPC(unsigned char& attr, char* upcdata) // attr = (upc.ADR<<4) | upc.Control; attr = 0; - int pos = 0; // Convert to mscdex format for (int i=0; i<7; i++) upcdata[i] = upc.MediaCatalog[i]; for (int i=0; i<7; i++) upcdata[i] = (upc.MediaCatalog[i*2] << 4) | (upc.MediaCatalog[i*2+1] & 0x0F); diff --git a/src/dos/cdrom_image.cpp b/src/dos/cdrom_image.cpp index 6e80394..a7b424d 100644 --- a/src/dos/cdrom_image.cpp +++ b/src/dos/cdrom_image.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: cdrom_image.cpp,v 1.15 2007/02/22 08:36:25 qbix79 Exp $ */ +/* $Id: cdrom_image.cpp,v 1.16 2007/06/12 20:22:08 c2woody Exp $ */ #include #include @@ -190,7 +190,7 @@ bool CDROM_Interface_Image::GetAudioTracks(int& stTrack, int& end, TMSF& leadOut bool CDROM_Interface_Image::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) { - if (track < 1 || track > tracks.size()) return false; + if (track < 1 || track > (int)tracks.size()) return false; FRAMES_TO_MSF(tracks[track - 1].start + 150, &start.min, &start.sec, &start.fr); attr = tracks[track - 1].attr; return true; @@ -254,7 +254,7 @@ bool CDROM_Interface_Image::ReadSectors(PhysPt buffer, bool raw, unsigned long s Bit8u* buf = new Bit8u[buflen]; bool success = true; //Gobliiins reads 0 sectors - for(int i = 0; i < num; i++) { + for(unsigned long i = 0; i < num; i++) { success = ReadSector(&buf[i * sectorSize], raw, sector + i); if (!success) break; } @@ -308,7 +308,7 @@ void CDROM_Interface_Image::CDAudioCallBack(Bitu len) } SDL_mutexP(player.mutex); - while (player.bufLen < len) { + while (player.bufLen < (Bits)len) { bool success; if (player.targetFrame > player.currFrame) success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame); @@ -607,7 +607,7 @@ bool CDROM_Interface_Image::GetRealFileName(string &filename, string &pathname) bool CDROM_Interface_Image::GetCueKeyword(string &keyword, istream &in) { in >> keyword; - for(int i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); + for(Bitu i = 0; i < keyword.size(); i++) keyword[i] = toupper(keyword[i]); return true; } diff --git a/src/dos/dev_con.h b/src/dos/dev_con.h index e5925df..af73cd6 100644 --- a/src/dos/dev_con.h +++ b/src/dos/dev_con.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dev_con.h,v 1.28 2007/01/11 18:08:54 c2woody Exp $ */ +/* $Id: dev_con.h,v 1.32 2007/06/30 19:33:45 c2woody Exp $ */ #include "dos_inc.h" #include "../ints/int10.h" @@ -49,6 +49,7 @@ private: Bit16u ncols; Bit8s savecol; Bit8s saverow; + bool warned; } ansi; }; @@ -265,12 +266,18 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { break; case 'f': case 'H':/* Cursor Pos*/ - if(ansi.data[0]==0) ansi.data[0]=1; - if(ansi.data[1]==0) ansi.data[1]=1; + if(!ansi.warned) { //Inform the debugger that ansi is used. + ansi.warned = true; + LOG(LOG_IOCTL,LOG_WARN)("ANSI SEQUENCES USED"); + } + /* Turn them into positions that are on the screen */ + if(ansi.data[0] == 0) ansi.data[0] = 1; + if(ansi.data[1] == 0) ansi.data[1] = 1; + if(ansi.data[0] > ansi.nrows) ansi.data[0] = (Bit8u)ansi.nrows; + if(ansi.data[1] > ansi.ncols) ansi.data[1] = (Bit8u)ansi.ncols; INT10_SetCursorPos(--(ansi.data[0]),--(ansi.data[1]),page); /*ansi=1 based, int10 is 0 based */ ClearAnsi(); break; - /* cursor up down and forward and backward only change the row or the col not both */ case 'A': /* cursor up*/ col=CURSOR_POS_COL(page) ; @@ -333,7 +340,7 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { ansi.saverow=CURSOR_POS_ROW(page); ClearAnsi(); break; - case 'K':/* erase till end of line (don't touch cursor) */ + case 'K': /* erase till end of line (don't touch cursor) */ col = CURSOR_POS_COL(page); row = CURSOR_POS_ROW(page); INT10_WriteChar(' ',ansi.attr,page,ansi.ncols-col,true); //Use this one to prevent scrolling when end of screen is reached @@ -341,6 +348,12 @@ bool device_CON::Write(Bit8u * data,Bit16u * size) { INT10_SetCursorPos(row,col,page); ClearAnsi(); break; + case 'M': /* delete line (NANSI) */ + col = CURSOR_POS_COL(page); + row = CURSOR_POS_ROW(page); + INT10_ScrollWindow(row,0,ansi.nrows-1,ansi.ncols-1,ansi.data[0]? -ansi.data[0] : -1,ansi.attr,0xFF); + ClearAnsi(); + break; case 'l':/* (if code =7) disable linewrap */ case 'p':/* reassign keys (needs strings) */ case 'i':/* printer stuff */ @@ -370,7 +383,7 @@ Bit16u device_CON::GetInformation(void) { Bit16u tail=mem_readw(BIOS_KEYBOARD_BUFFER_TAIL); if ((head==tail) && !readcache) return 0x80D3; /* No Key Available */ - if (real_readw(0x40,head)) return 0x8093; /* Key Available */ + if (readcache || real_readw(0x40,head)) return 0x8093; /* Key Available */ /* remove the zero from keyboard buffer */ Bit16u start=mem_readw(BIOS_KEYBOARD_BUFFER_START); @@ -391,6 +404,7 @@ device_CON::device_CON() { ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1; ansi.saverow=0; ansi.savecol=0; + ansi.warned=false; ClearAnsi(); } diff --git a/src/dos/dos.cpp b/src/dos/dos.cpp index 9b40866..ccd3ca9 100644 --- a/src/dos/dos.cpp +++ b/src/dos/dos.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos.cpp,v 1.99 2007/01/13 08:35:49 qbix79 Exp $ */ +/* $Id: dos.cpp,v 1.104 2007/07/27 19:17:23 qbix79 Exp $ */ #include #include @@ -45,11 +45,11 @@ void DOS_SetError(Bit16u code) { #define DATA_TRANSFERS_TAKE_CYCLES 1 #ifdef DATA_TRANSFERS_TAKE_CYCLES #include "cpu.h" -static inline void modify_cycles(Bitu value) { +static inline void modify_cycles(Bits value) { if((4*value+5) < CPU_Cycles) CPU_Cycles -= 4*value; else CPU_Cycles = 5; } #else -static inline void modify_cycles(Bitu /* value */) { +static inline void modify_cycles(Bits /* value */) { return; } #endif @@ -191,14 +191,12 @@ static Bitu DOS_21Handler(void) { break; case 0x0c: /* Flush Buffer and read STDIN call */ { + /* flush STDIN-buffer */ + Bit8u c;Bit16u n; + while (DOS_GetSTDINStatus()) { + n=1; DOS_ReadFile(STDIN,&c,&n); + } switch (reg_al) { - case 0x0: - /* flush STDIN-buffer */ - Bit8u c;Bit16u n; - while (DOS_GetSTDINStatus()) { - n=1; DOS_ReadFile(STDIN,&c,&n); - } - break; case 0x1: case 0x6: case 0x7: @@ -213,6 +211,7 @@ static Bitu DOS_21Handler(void) { break; default: // LOG_ERROR("DOS:0C:Illegal Flush STDIN Buffer call %d",reg_al); + reg_al=0; break; } } @@ -289,7 +288,7 @@ static Bitu DOS_21Handler(void) { LOG(LOG_FCB,LOG_NORMAL)("DOS:0x22 FCB-Random write used, result:al=%d",reg_al); break; case 0x23: /* Get file size for FCB */ - if (DOS_FCBGetFileSize(SegValue(ds),reg_dx,reg_cx)) reg_al = 0x00; + if (DOS_FCBGetFileSize(SegValue(ds),reg_dx)) reg_al = 0x00; else reg_al = 0xFF; break; case 0x24: /* Set Random Record number for FCB */ @@ -360,7 +359,10 @@ static Bitu DOS_21Handler(void) { break; case 0x2d: /* Set System Time */ LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Set System Time not supported"); - reg_al=0; /* Noone is changing system time */ + //Check input parameters nonetheless + if( reg_ch > 23 || reg_cl > 59 || reg_dh > 59 || reg_dl > 99 ) + reg_al = 0xff; + else reg_al = 0; break; case 0x2e: /* Set Verify flag */ dos.verify=(reg_al==1); @@ -386,12 +388,15 @@ static Bitu DOS_21Handler(void) { dos.return_code=reg_al; //Officially a field in the SDA dos.return_mode=RETURN_TSR; break; - case 0x32: /* Get drive parameter block for specific drive */ + case 0x1f: /* Get drive parameter block for default drive */ + case 0x32: /* Get drive parameter block for specific drive */ { /* Officially a dpb should be returned as well. The disk detection part is implemented */ - Bitu drive=reg_dl;if(!drive) drive=dos.current_drive;else drive--; + Bitu drive=reg_dl;if(!drive || reg_ah==0x1f) drive=dos.current_drive;else drive--; if(Drives[drive]) { - reg_al=0x00; - LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block."); + reg_al = 0x00; + SegSet16(ds,dos.tables.dpb); + reg_bx = drive;//Faking only the first entry (that is the driveletter) + LOG(LOG_DOSMISC,LOG_ERROR)("Get drive parameter block."); } else { reg_al=0xff; } @@ -988,23 +993,21 @@ static Bitu DOS_21Handler(void) { LOG(LOG_DOSMISC,LOG_NORMAL)("DOS:Windows long file name support call %2X",reg_al); break; - case 0x68: /* FFLUSH Commit file */ - CALLBACK_SCF(false); //mirek - case 0xE0: - case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */ - case 0x6b: /* NULL Function */ - case 0x61: /* UNUSED */ - case 0xEF: /* Used in Ancient Art Of War CGA */ - case 0x1f: /* Get drive parameter block for default drive */ - + case 0x68: /* FFLUSH Commit file */ + CALLBACK_SCF(false); //mirek + case 0xE0: + case 0x18: /* NULL Function for CP/M compatibility or Extended rename FCB */ + case 0x1d: /* NULL Function for CP/M compatibility or Extended rename FCB */ + case 0x1e: /* NULL Function for CP/M compatibility or Extended rename FCB */ + case 0x20: /* NULL Function for CP/M compatibility or Extended rename FCB */ + case 0x6b: /* NULL Function */ + case 0x61: /* UNUSED */ + case 0xEF: /* Used in Ancient Art Of War CGA */ case 0x5c: /* FLOCK File region locking */ case 0x5e: /* More Network Functions */ - default: - LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); - reg_al=0x00; /* default value */ + default: + LOG(LOG_DOSMISC,LOG_ERROR)("DOS:Unhandled call %02X al=%02X. Set al to default of 0",reg_ah,reg_al); + reg_al=0x00; /* default value */ break; }; return CBRET_NONE; diff --git a/src/dos/dos_classes.cpp b/src/dos/dos_classes.cpp index 1a75e92..e8df4b1 100644 --- a/src/dos/dos_classes.cpp +++ b/src/dos/dos_classes.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_classes.cpp,v 1.49 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: dos_classes.cpp,v 1.52 2007/06/13 07:25:14 qbix79 Exp $ */ #include #include @@ -179,7 +179,7 @@ Bit16u DOS_PSP::rootpsp = 0; void DOS_PSP::MakeNew(Bit16u mem_size) { /* get previous */ - DOS_PSP prevpsp(dos.psp()); +// DOS_PSP prevpsp(dos.psp()); /* Clear it first */ Bitu i; for (i=0;isize); +// sSave(sFCB,rndm,0); // breaks Jewels of darkness. + Bit8u temp = RealHandle(_fhandle); + Bit32u size = 0; + Files[temp]->Seek(&size,DOS_SEEK_END); + sSave(sFCB,filesize,size); + size = 0; + Files[temp]->Seek(&size,DOS_SEEK_SET); sSave(sFCB,time,Files[temp]->time); sSave(sFCB,date,Files[temp]->date); } diff --git a/src/dos/dos_devices.cpp b/src/dos/dos_devices.cpp index c12bf09..480f828 100644 --- a/src/dos/dos_devices.cpp +++ b/src/dos/dos_devices.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_devices.cpp,v 1.16 2007/01/13 08:35:49 qbix79 Exp $ */ +/* $Id: dos_devices.cpp,v 1.18 2007/06/14 08:23:46 qbix79 Exp $ */ #include #include "dosbox.h" @@ -92,12 +92,10 @@ bool DOS_Device::WriteToControlChannel(PhysPt bufptr,Bit16u size,Bit16u * retcod } DOS_File::DOS_File(const DOS_File& orig) { - type=orig.type; flags=orig.flags; time=orig.time; date=orig.date; attr=orig.attr; - size=orig.size; refCtr=orig.refCtr; open=orig.open; name=0; @@ -107,12 +105,10 @@ DOS_File::DOS_File(const DOS_File& orig) { } DOS_File & DOS_File::operator= (const DOS_File & orig) { - type=orig.type; flags=orig.flags; time=orig.time; date=orig.date; attr=orig.attr; - size=orig.size; refCtr=orig.refCtr; open=orig.open; if(name) { @@ -124,7 +120,7 @@ DOS_File & DOS_File::operator= (const DOS_File & orig) { return *this; } -Bit8u DOS_FindDevice(char * name) { +Bit8u DOS_FindDevice(char const * name) { /* should only check for the names before the dot and spacepadded */ // STDAUX is alias for COM1 // A bit of a hack, but no application will probably use stdaux to determine wether a directory exists diff --git a/src/dos/dos_files.cpp b/src/dos/dos_files.cpp index 6bc05e8..b1305b9 100644 --- a/src/dos/dos_files.cpp +++ b/src/dos/dos_files.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_files.cpp,v 1.81 2007/01/08 21:20:23 qbix79 Exp $ */ +/* $Id: dos_files.cpp,v 1.90 2007/06/29 10:24:43 qbix79 Exp $ */ #include #include @@ -52,7 +52,7 @@ void DOS_SetDefaultDrive(Bit8u drive) { if (drive<=DOS_DRIVES && ((drive<2) || Drives[drive])) dos.current_drive = drive; } -bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { +bool DOS_MakeName(char const * const name,char * const fullname,Bit8u * drive) { if(!name || *name == 0 || *name == ' ') { /* Both \0 and space are seperators and @@ -60,23 +60,23 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { DOS_SetError(DOSERR_FILE_NOT_FOUND); return false; } - + const char * name_int = name; char tempdir[DOS_PATHLENGTH]; char upname[DOS_PATHLENGTH]; Bitu r,w; *drive=dos.current_drive; /* First get the drive */ - if (name[1]==':') { - *drive=(name[0] | 0x20)-'a'; - name+=2; + if (name_int[1]==':') { + *drive=(name_int[0] | 0x20)-'a'; + name_int+=2; } if (*drive>=DOS_DRIVES || !Drives[*drive]) { DOS_SetError(DOSERR_PATH_NOT_FOUND); return false; } r=0;w=0; - while (name[r]!=0 && (r='a') && (c<='z')) {upname[w++]=c-32;continue;} if ((c>='A') && (c<='Z')) {upname[w++]=c;continue;} if ((c>='0') && (c<='9')) {upname[w++]=c;continue;} @@ -90,6 +90,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { case '!': case '%': case '{': case '}': case '`': case '~': case '_': case '-': case '.': case '*': case '?': case '&': case '\'': case '+': case '^': case 246: case 255: case 0xa0: + case 0xe5: upname[w++]=c; break; default: @@ -105,7 +106,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { else fullname[0]=0; Bit32u lastdir=0;Bit32u t=0; while (fullname[t]!=0) { - if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t; + if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t; t++; }; r=0;w=0; @@ -124,7 +125,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { Bit32s iDown, cDots; bool dots = true; - Bit32u templen =strlen(tempdir); + Bit32s templen=(Bit32s)strlen(tempdir); for(iDown=0;(iDown < templen) && dots;iDown++) if(tempdir[iDown] != '.') dots = false; @@ -133,7 +134,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { cDots = templen - 1; if(dots && (cDots > 0)) { - for(iDown=strlen(fullname)-1;iDown>=0;iDown--) + for(iDown=(Bit32s)strlen(fullname)-1;iDown>=0;iDown--) { if(fullname[iDown]=='\\' || iDown==0) { @@ -144,7 +145,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { } } fullname[lastdir]=0; - Bit32u t=0;lastdir=0; + t=0;lastdir=0; while (fullname[t]!=0) { if ((fullname[t]=='\\') && (fullname[t+1]!=0))lastdir=t; t++; @@ -173,7 +174,7 @@ bool DOS_MakeName(char * name,char * fullname,Bit8u * drive) { return true; } -bool DOS_GetCurrentDir(Bit8u drive,char * buffer) { +bool DOS_GetCurrentDir(Bit8u drive,char * const buffer) { if (drive==0) drive=DOS_GetDefaultDrive(); else drive--; if ((drive>DOS_DRIVES) || (!Drives[drive])) { @@ -184,7 +185,7 @@ bool DOS_GetCurrentDir(Bit8u drive,char * buffer) { return true; } -bool DOS_ChangeDir(char * dir) { +bool DOS_ChangeDir(char const * const dir) { Bit8u drive;char fulldir[DOS_PATHLENGTH]; if (!DOS_MakeName(dir,fulldir,&drive)) return false; @@ -197,7 +198,7 @@ bool DOS_ChangeDir(char * dir) { return false; } -bool DOS_MakeDir(char * dir) { +bool DOS_MakeDir(char const * const dir) { Bit8u drive;char fulldir[DOS_PATHLENGTH]; size_t len = strlen(dir); if(!len || dir[len-1] == '\\') { @@ -215,7 +216,7 @@ bool DOS_MakeDir(char * dir) { return false; } -bool DOS_RemoveDir(char * dir) { +bool DOS_RemoveDir(char const * const dir) { /* We need to do the test before the removal as can not rely on * the host to forbid removal of the current directory. * We never change directory. Everything happens in the drives. @@ -243,7 +244,7 @@ bool DOS_RemoveDir(char * dir) { return false; } -bool DOS_Rename(char * oldname,char * newname) { +bool DOS_Rename(char const * const oldname,char const * const newname) { Bit8u driveold;char fullold[DOS_PATHLENGTH]; Bit8u drivenew;char fullnew[DOS_PATHLENGTH]; if (!DOS_MakeName(oldname,fullold,&driveold)) return false; @@ -382,13 +383,14 @@ bool DOS_CloseFile(Bit16u entry) { return true; } -static bool PathExists(char* name) { - char* leading = strrchr(name,'\\'); +static bool PathExists(char const * const name) { + const char* leading = strrchr(name,'\\'); if(!leading) return true; char temp[CROSS_LEN]; strcpy(temp,name); - leading = strrchr(temp,'\\'); - *leading = 0; + char * lead = strrchr(temp,'\\'); + if (lead == temp) return true; + *lead = 0; Bit8u drive;char fulldir[DOS_PATHLENGTH]; if (!DOS_MakeName(temp,fulldir,&drive)) return false; if(!Drives[drive]->TestDir(fulldir)) return false; @@ -396,7 +398,7 @@ static bool PathExists(char* name) { } -bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { +bool DOS_CreateFile(char const * name,Bit16u attributes,Bit16u * entry) { // Creation of a device is the same as opening it // Tc201 installer if (DOS_FindDevice(name) != DOS_DEVICES) @@ -437,14 +439,14 @@ bool DOS_CreateFile(char * name,Bit16u attributes,Bit16u * entry) { } } -bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { +bool DOS_OpenFile(char const * name,Bit8u flags,Bit16u * entry) { /* First check for devices */ if (flags>2) LOG(LOG_FILES,LOG_ERROR)("Special file open command %X file %s",flags,name); else LOG(LOG_FILES,LOG_NORMAL)("file open command %X file %s",flags,name); DOS_PSP psp(dos.psp()); Bit16u attr = 0; - Bit8u devnum = DOS_FindDevice((char *)name); + Bit8u devnum = DOS_FindDevice(name); bool device = (devnum != DOS_DEVICES); if(!device && DOS_GetFileAttr(name,&attr)) { //DON'T ALLOW directories to be openened.(skip test if file is device). @@ -499,7 +501,7 @@ bool DOS_OpenFile(char * name,Bit8u flags,Bit16u * entry) { } } -bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status) +bool DOS_OpenFileExtended(char const * name, Bit16u flags, Bit16u createAttr, Bit16u action, Bit16u *entry, Bit16u* status) // FIXME: Not yet supported : Bit 13 of flags (int 0x24 on critical error { Bit16u result = 0; @@ -525,7 +527,7 @@ bool DOS_OpenFileExtended(char *name, Bit16u flags, Bit16u createAttr, Bit16u ac return true; }; -bool DOS_UnlinkFile(char * name) { +bool DOS_UnlinkFile(char const * const name) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; if(Drives[drive]->FileUnlink(fullname)){ @@ -536,7 +538,7 @@ bool DOS_UnlinkFile(char * name) { } } -bool DOS_GetFileAttr(char * name,Bit16u * attr) { +bool DOS_GetFileAttr(char const * const name,Bit16u * attr) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; if (Drives[drive]->GetFileAttr(fullname,attr)) { @@ -547,7 +549,7 @@ bool DOS_GetFileAttr(char * name,Bit16u * attr) { } } -bool DOS_SetFileAttr(char * name,Bit16u attr) +bool DOS_SetFileAttr(char const * const name,Bit16u attr) // this function does not change the file attributs // it just does some tests if file is available // returns false when using on cdrom (stonekeep) @@ -562,7 +564,7 @@ bool DOS_SetFileAttr(char * name,Bit16u attr) return Drives[drive]->GetFileAttr(fullname,&attrTemp); } -bool DOS_Canonicalize(char * name,char * big) { +bool DOS_Canonicalize(char const * const name,char * const big) { //TODO Add Better support for devices and shit but will it be needed i doubt it :) Bit8u drive; char fullname[DOS_PATHLENGTH]; @@ -637,11 +639,11 @@ bool DOS_ForceDuplicateEntry(Bit16u entry,Bit16u newentry) { -bool DOS_CreateTempFile(char * name,Bit16u * entry) { +bool DOS_CreateTempFile(char * const name,Bit16u * entry) { /* First add random crap to the end of the name and try to open */ - /* Todo maybe check for euhm existence of the path name */ char * tempname; tempname=name+strlen(name); + dos.errorcode=0; do { Bit32u i; for (i=0;i<8;i++) { @@ -652,7 +654,8 @@ bool DOS_CreateTempFile(char * name,Bit16u * entry) { tempname[i]=(rand()%26)+'A'; } tempname[12]=0; - } while (!DOS_CreateFile(name,0,entry)); + } while ((!DOS_CreateFile(name,0,entry)) && (dos.errorcode==DOSERR_FILE_ALREADY_EXISTS)); + if (dos.errorcode) return false; return true; } @@ -688,7 +691,7 @@ Bit8u FCB_Parsename(Bit16u seg,Bit16u offset,Bit8u parser ,char *string, Bit8u * char drive[2]; char name[9]; char ext[4]; - } part GCC_ATTRIBUTE (packed) ; + } GCC_ATTRIBUTE (packed) part; char full[DOS_FCBNAME]; } fcb_name; #ifdef _MSC_VER @@ -773,7 +776,7 @@ savefcb: return ret; } -static void DTAExtendName(char * name,char * filename,char * ext) { +static void DTAExtendName(char * const name,char * const filename,char * const ext) { char * find=strchr(name,'.'); if (find) { strcpy(ext,find+1); @@ -878,10 +881,9 @@ Bit8u DOS_FCBRead(Bit16u seg,Bit16u offset,Bit16u recno) { Bit16u toread=rec_size; if (!DOS_ReadFile(fhandle,dos_copybuf,&toread)) return FCB_READ_NODATA; if (toread==0) return FCB_READ_NODATA; - if (toread0;i--) mem_writeb(fill++,0); + if (toread < rec_size) { //Zero pad copybuffer to rec_size + Bitu i = toread; + while(i < rec_size) dos_copybuf[i++] = 0; } MEM_BlockWrite(Real2Phys(dos.dta())+recno*rec_size,dos_copybuf,rec_size); if (++cur_rec>127) { cur_block++;cur_rec=0; } @@ -927,10 +929,15 @@ Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { * random read updates old block and old record to reflect the random data * before the read!!!!!!!!! and the random data is not updated! (user must do this) * Random block read updates these fields to reflect the state after the read! + */ + +/* BUG: numRec should return the amount of records read! + * Not implemented yet as I'm unsure how to count on error states (partial/failed) */ DOS_FCB fcb(seg,offset); - Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error; + Bit32u random;Bit16u old_block;Bit8u old_rec; + Bit8u error=0; /* Set the correct record from the random data */ fcb.GetRandom(random); @@ -952,7 +959,8 @@ Bit8u DOS_FCBRandomRead(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { /* see FCB_RandomRead */ DOS_FCB fcb(seg,offset); - Bit32u random;Bit16u old_block;Bit8u old_rec;Bit8u error; + Bit32u random;Bit16u old_block;Bit8u old_rec; + Bit8u error=0; /* Set the correct record from the random data */ fcb.GetRandom(random); @@ -971,13 +979,14 @@ Bit8u DOS_FCBRandomWrite(Bit16u seg,Bit16u offset,Bit16u numRec,bool restore) { return error; } -bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset,Bit16u numRec) { +bool DOS_FCBGetFileSize(Bit16u seg,Bit16u offset) { char shortname[DOS_PATHLENGTH];Bit16u entry;Bit8u handle;Bit16u rec_size; DOS_FCB fcb(seg,offset); fcb.GetName(shortname); if (!DOS_OpenFile(shortname,0,&entry)) return false; - handle=RealHandle(entry); - Bit32u size=Files[handle]->size; + handle = RealHandle(entry); + Bit32u size = 0; + Files[handle]->Seek(&size,DOS_SEEK_END); DOS_CloseFile(entry);fcb.GetSeqData(handle,rec_size); Bit32u random=(size/rec_size); if (size % rec_size) random++; @@ -1024,7 +1033,7 @@ void DOS_FCBSetRandomRecord(Bit16u seg, Bit16u offset) { } -bool DOS_FileExists(char * name) { +bool DOS_FileExists(char const * const name) { char fullname[DOS_PATHLENGTH];Bit8u drive; if (!DOS_MakeName(name,fullname,&drive)) return false; return Drives[drive]->FileExists(fullname); @@ -1033,7 +1042,7 @@ bool DOS_FileExists(char * name) { bool DOS_GetAllocationInfo(Bit8u drive,Bit16u * _bytes_sector,Bit8u * _sectors_cluster,Bit16u * _total_clusters) { if (!drive) drive=dos.current_drive; else drive--; - if (!Drives[drive]) return false; + if (drive >= DOS_DRIVES || !Drives[drive]) return false; Bit16u _free_clusters; Drives[drive]->AllocationInfo(_bytes_sector,_sectors_cluster,_total_clusters,&_free_clusters); SegSet16(ds,RealSeg(dos.tables.mediaid)); @@ -1050,8 +1059,7 @@ bool DOS_SetDrive(Bit8u drive) { } }; -bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate) -{ +bool DOS_GetFileDate(Bit16u entry, Bit16u* otime, Bit16u* odate) { Bit32u handle=RealHandle(entry); if (handle>=DOS_FILES) { DOS_SetError(DOSERR_INVALID_HANDLE); diff --git a/src/dos/dos_keyboard_layout.cpp b/src/dos/dos_keyboard_layout.cpp index 79e8af3..f19b49d 100644 --- a/src/dos/dos_keyboard_layout.cpp +++ b/src/dos/dos_keyboard_layout.cpp @@ -37,7 +37,7 @@ static FILE* OpenDosboxFile(const char* name) { localDrive* ldp=0; // try to build dos name - if (DOS_MakeName((char*)name,fullname,&drive)) { + if (DOS_MakeName(name,fullname,&drive)) { try { // try to open file on mounted drive first ldp=dynamic_cast(Drives[drive]); diff --git a/src/dos/dos_memory.cpp b/src/dos/dos_memory.cpp index 0fa042f..9785e87 100644 --- a/src/dos/dos_memory.cpp +++ b/src/dos/dos_memory.cpp @@ -352,7 +352,7 @@ bool DOS_LinkUMBsToMemChain(Bit16u linkstate) { /* Scan MCB-chain for last block before UMB-chain */ Bit16u mcb_segment=dos.firstMCB; - Bit16u prev_mcb_segment; + Bit16u prev_mcb_segment=dos.firstMCB; DOS_MCB mcb(mcb_segment); while ((mcb_segment!=umb_start) && (mcb.GetType()!=0x5a)) { prev_mcb_segment=mcb_segment; diff --git a/src/dos/dos_mscdex.cpp b/src/dos/dos_mscdex.cpp index 7aaf95e..b452262 100644 --- a/src/dos/dos_mscdex.cpp +++ b/src/dos/dos_mscdex.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_mscdex.cpp,v 1.45 2007/01/21 16:21:22 c2woody Exp $ */ +/* $Id: dos_mscdex.cpp,v 1.50 2007/07/20 18:22:28 qbix79 Exp $ */ #include #include @@ -64,7 +64,7 @@ public: void SetDriveLetter (Bit8u letter) { sSave(sDeviceHeader,driveLetter,letter); }; void SetNumSubUnits (Bit8u num) { sSave(sDeviceHeader,numSubUnits,num); }; Bit8u GetNumSubUnits (void) { return sGet(sDeviceHeader,numSubUnits); }; - void SetName (char* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); }; + void SetName (char const* _name) { MEM_BlockWrite(pt+offsetof(sDeviceHeader,name),_name,8); }; void SetInterrupt (Bit16u ofs) { sSave(sDeviceHeader,interrupt,ofs); }; void SetStrategy (Bit16u ofs) { sSave(sDeviceHeader,strategy,ofs); }; @@ -81,7 +81,7 @@ public: Bit16u wReserved; Bit8u driveLetter; Bit8u numSubUnits; - } TDeviceHeader; + } GCC_ATTRIBUTE(packed) TDeviceHeader; #ifdef _MSC_VER #pragma pack() #endif @@ -190,12 +190,14 @@ void CMscdex::GetDrives(PhysPt data) bool CMscdex::IsValidDrive(Bit16u _drive) { + _drive &= 0xff; //Only lowerpart (Ultimate domain) for (Bit16u i=0; i>16; - Bit16u offm = start&0xFFFF; + Bit16u segm = (Bit16u)(start>>16); + Bit16u offm = (Bit16u)(start&0xFFFF); while(start != 0xFFFFFFFF) { - segm = start>>16; - offm = start&0xFFFF; + segm = (Bit16u)(start>>16); + offm = (Bit16u)(start&0xFFFF); start = real_readd(segm,offm); } real_writed(segm,offm,seg<<16); @@ -876,14 +878,17 @@ static Bit16u MSCDEX_IOCTL_Input(PhysPt buffer,Bit8u drive_unit) { mscdex->GetCurrentPos(drive_unit,pos); Bit8u addr_mode = mem_readb(buffer+1); if (addr_mode==0) { // HSG - mem_writed(buffer+2,MSF_TO_FRAMES (pos.min, pos.sec, pos.fr)); + Bit32u frames=MSF_TO_FRAMES(pos.min, pos.sec, pos.fr); + if (frames<150) MSCDEX_LOG("MSCDEX: Get position: invalid position %d:%d:%d", pos.min, pos.sec, pos.fr); + else frames-=150; + mem_writed(buffer+2,frames); } else if (addr_mode==1) { // Red book mem_writeb(buffer+2,pos.fr); mem_writeb(buffer+3,pos.sec); mem_writeb(buffer+4,pos.min); mem_writeb(buffer+5,0x00); } else { - LOG_MSG("MSCDEX: Get position: invalid address mode %x",addr_mode); + MSCDEX_LOG("MSCDEX: Get position: invalid address mode %x",addr_mode); return 0x03; // invalid function } }break; diff --git a/src/dos/dos_programs.cpp b/src/dos/dos_programs.cpp index 3003edb..0f4260a 100644 --- a/src/dos/dos_programs.cpp +++ b/src/dos/dos_programs.cpp @@ -16,8 +16,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_programs.cpp,v 1.69 2007/02/22 08:37:12 qbix79 Exp $ */ +/* $Id: dos_programs.cpp,v 1.76 2007/07/02 14:10:27 c2woody Exp $ */ +#include "dosbox.h" #include #include #include @@ -34,6 +35,12 @@ #include "dos_inc.h" #include "bios.h" +#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H +#include +#include +#endif + + #if defined(OS2) #define INCL DOSFILEMGR #define INCL_DOSERRORS @@ -46,6 +53,24 @@ Bitu DEBUG_EnableDebugger(void); void MSCDEX_SetCDInterface(int intNr, int forceCD); +//Helper function for mount and imgmount to correctly find the path +static void ResolveHomedir(std::string & temp_line) { + if(!temp_line.size() || temp_line[0] != '~') return; //No ~ + + if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant + char * home = getenv("HOME"); + if(home) temp_line.replace(0,1,std::string(home)); +#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H + } else { // The ~username variant + std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT); + if(namelen == std::string::npos) namelen = temp_line.size(); + std::string username = temp_line.substr(1,namelen - 1); + struct passwd* pass = getpwnam(username.c_str()); + if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~) +#endif // USERNAME lookup code + } +} + class MOUNT : public Program { public: void Run(void) @@ -108,24 +133,30 @@ public: Bit8u mediaid; std::string str_size; if (type=="floppy") { - str_size="512,1,2847,2847";/* All space free */ + str_size="512,1,2880,2880";/* All space free */ mediaid=0xF0; /* Floppy 1.44 media */ } else if (type=="dir") { + // 512*127*16513==~1GB total size + // 512*127*1700==~100MB total free size str_size="512,127,16513,1700"; mediaid=0xF8; /* Hard Disk */ } else if (type=="cdrom") { - str_size="650,127,16513,1700"; + str_size="2048,1,65535,0"; mediaid=0xF8; /* Hard Disk */ } else { WriteOut(MSG_Get("PROGAM_MOUNT_ILL_TYPE"),type.c_str()); return; } - /* Parse the free space in mb's */ + /* Parse the free space in mb's (kb's for floppies) */ std::string mb_size; if(cmd->FindString("-freesize",mb_size,true)) { char teststr[1024]; Bit16u sizemb = static_cast(atoi(mb_size.c_str())); - sprintf(teststr,"512,127,16513,%d",sizemb*1024*1024/(512*127)); + if (type=="floppy") { + sprintf(teststr,"512,1,2880,%d",sizemb*1024/(512*1)); + } else { + sprintf(teststr,"512,127,16513,%d",sizemb*1024*1024/(512*127)); + } str_size=teststr; } @@ -184,11 +215,9 @@ public: #else if (stat(temp_line.c_str(),&test)) { failed = true; - if(temp_line.size() && temp_line[0] == '~') { - char * home = getenv("HOME"); - if(home) temp_line.replace(0,1,std::string(home)); - if(!stat(temp_line.c_str(),&test)) failed = false; - } + ResolveHomedir(temp_line); + //Try again after resolving ~ + if(!stat(temp_line.c_str(),&test)) failed = false; } if(failed) { #endif @@ -220,9 +249,15 @@ public: int num = -1; cmd->FindInt("-usecd",num,true); int error; - if (cmd->FindExist("-aspi",false)) MSCDEX_SetCDInterface(CDROM_USE_ASPI, num); else - if (cmd->FindExist("-ioctl",false)) MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num); - else MSCDEX_SetCDInterface(CDROM_USE_SDL, num); + if (cmd->FindExist("-aspi",false)) { + MSCDEX_SetCDInterface(CDROM_USE_ASPI, num); + } else if (cmd->FindExist("-ioctl",false)) { + MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num); + } else if (cmd->FindExist("-noioctl",false)) { + MSCDEX_SetCDInterface(CDROM_USE_SDL, num); + } else { + MSCDEX_SetCDInterface(CDROM_USE_IOCTL, num); + } newdrive = new cdromDrive(drive,temp_line.c_str(),sizes[0],bit8size,sizes[2],0,mediaid,error); // Check Mscdex, if it worked out... switch (error) { @@ -374,21 +409,30 @@ private: ldp=dynamic_cast(Drives[drive]); if(!ldp) return NULL; - tmpfile = ldp->GetSystemFilePtr(fullname, "r"); + tmpfile = ldp->GetSystemFilePtr(fullname, "rb"); if(tmpfile == NULL) { if (!tryload) *error=1; return NULL; } - fclose(tmpfile); - tmpfile = ldp->GetSystemFilePtr(fullname, "rb+"); - if(tmpfile == NULL) { - if (!tryload) *error=2; - return NULL; - } + // get file size fseek(tmpfile,0L, SEEK_END); *ksize = (ftell(tmpfile) / 1024); *bsize = ftell(tmpfile); + fclose(tmpfile); + + tmpfile = ldp->GetSystemFilePtr(fullname, "rb+"); + if(tmpfile == NULL) { +// if (!tryload) *error=2; +// return NULL; + WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED")); + tmpfile = ldp->GetSystemFilePtr(fullname, "rb"); + if(tmpfile == NULL) { + if (!tryload) *error=1; + return NULL; + } + } + return tmpfile; } catch(...) { @@ -401,12 +445,19 @@ private: FILE* tmpfile = getFSFile_mounted(filename,ksize,bsize,&error); if(tmpfile) return tmpfile; //File not found on mounted filesystem. Try regular filesystem - tmpfile = fopen(filename,"rb+"); + std::string filename_s(filename); + ResolveHomedir(filename_s); + tmpfile = fopen(filename_s.c_str(),"rb+"); if(!tmpfile) { - if( (tmpfile = fopen(filename,"r")) ) { + if( (tmpfile = fopen(filename_s.c_str(),"rb")) ) { //File exists; So can't be opened in correct mode => error 2 - fclose(tmpfile); - if(tryload) error = 2; +// fclose(tmpfile); +// if(tryload) error = 2; + WriteOut(MSG_Get("PROGRAM_BOOT_WRITE_PROTECTED")); + fseek(tmpfile,0L, SEEK_END); + *ksize = (ftell(tmpfile) / 1024); + *bsize = ftell(tmpfile); + return tmpfile; } // Give the delayed errormessages from the mounted variant (or from above) if(error == 1) WriteOut(MSG_Get("PROGRAM_BOOT_NOT_EXIST")); @@ -886,6 +937,7 @@ public: Bit8u mediaid; if (type=="floppy" || type=="hdd" || type=="iso") { Bit16u sizes[4]; + bool imgsizedetect=false; std::string str_size; mediaid=0xF8; @@ -899,21 +951,21 @@ public: } cmd->FindString("-size",str_size,true); if ((type=="hdd") && (str_size.size()==0)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_SPECIFY_GEOMETRY")); - return; + imgsizedetect=true; + } else { + char number[20]; + const char * scan=str_size.c_str(); + Bitu index=0;Bitu count=0; + + while (*scan) { + if (*scan==',') { + number[index]=0;sizes[count++]=atoi(number); + index=0; + } else number[index++]=*scan; + scan++; + } + number[index]=0;sizes[count++]=atoi(number); } - char number[20]; - const char * scan=str_size.c_str(); - Bitu index=0;Bitu count=0; - - while (*scan) { - if (*scan==',') { - number[index]=0;sizes[count++]=atoi(number); - index=0; - } else number[index++]=*scan; - scan++; - } - number[index]=0;sizes[count++]=atoi(number); if(fstype=="fat" || fstype=="iso") { // get the drive letter @@ -947,29 +999,36 @@ public: struct stat test; if (stat(temp_line.c_str(),&test)) { - // convert dosbox filename to system filename - char fullname[CROSS_LEN]; - char tmp[CROSS_LEN]; - safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN); - - Bit8u dummy; - if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE")); - return; - } - - localDrive *ldp = (localDrive*)Drives[dummy]; - ldp->GetSystemFilename(tmp, fullname); - temp_line = tmp; - - if (stat(temp_line.c_str(),&test)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND")); - return; - } - - if ((test.st_mode & S_IFDIR)) { - WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT")); - return; + //See if it works if the ~ are written out + std::string homedir(temp_line); + ResolveHomedir(homedir); + if(!stat(homedir.c_str(),&test)) { + temp_line = homedir; + } else { + // convert dosbox filename to system filename + char fullname[CROSS_LEN]; + char tmp[CROSS_LEN]; + safe_strncpy(tmp, temp_line.c_str(), CROSS_LEN); + + Bit8u dummy; + if (!DOS_MakeName(tmp, fullname, &dummy) || strncmp(Drives[dummy]->GetInfo(),"local directory",15)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_NON_LOCAL_DRIVE")); + return; + } + + localDrive *ldp = (localDrive*)Drives[dummy]; + ldp->GetSystemFilename(tmp, fullname); + temp_line = tmp; + + if (stat(temp_line.c_str(),&test)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_FILE_NOT_FOUND")); + return; + } + + if ((test.st_mode & S_IFDIR)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_MOUNT")); + return; + } } } paths.push_back(temp_line); @@ -986,6 +1045,35 @@ public: } if(fstype=="fat") { + if (imgsizedetect) { + FILE * diskfile = fopen(temp_line.c_str(), "rb+"); + if(!diskfile) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE")); + return; + } + fseek(diskfile, 0L, SEEK_END); + Bit32u fcsize = (Bit32u)(ftell(diskfile) / 512L); + Bit8u buf[512]; + fseek(diskfile, 0L, SEEK_SET); + if (fread(buf,sizeof(Bit8u),512,diskfile)<512) { + fclose(diskfile); + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_IMAGE")); + return; + } + fclose(diskfile); + if ((buf[510]!=0x55) || (buf[511]!=0xaa)) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY")); + return; + } + Bitu sectors=(Bitu)(fcsize/(16*63)); + if (sectors*16*63!=fcsize) { + WriteOut(MSG_Get("PROGRAM_IMGMOUNT_INVALID_GEOMETRY")); + return; + } + sizes[0]=512; sizes[1]=63; sizes[2]=16; sizes[3]=sectors; + LOG_MSG("autosized image file: %d:%d:%d:%d",sizes[0],sizes[1],sizes[2],sizes[3]); + } + newdrive=new fatDrive(temp_line.c_str(),sizes[0],sizes[1],sizes[2],sizes[3],0); if(!(dynamic_cast(newdrive))->created_succesfully) { delete newdrive; @@ -1039,7 +1127,9 @@ public: MSCDEX_SetCDInterface(CDROM_USE_SDL, -1); // create new drives for all images std::vector isoDisks; - for (int i = 0; i < paths.size(); i++) { + std::vector::size_type i; + std::vector::size_type ct; + for (i = 0; i < paths.size(); i++) { int error = -1; DOS_Drive* newDrive = new isoDrive(drive, paths[i].c_str(), mediaid, error); isoDisks.push_back(newDrive); @@ -1055,15 +1145,15 @@ public: } // error: clean up and leave if (error) { - for(int i = 0; i < isoDisks.size(); i++) { - delete isoDisks[i]; + for(ct = 0; ct < isoDisks.size(); ct++) { + delete isoDisks[ct]; } return; } } // Update DriveManager - for(int i = 0; i < isoDisks.size(); i++) { - DriveManager::AppendDisk(drive - 'A', isoDisks[i]); + for(ct = 0; ct < isoDisks.size(); ct++) { + DriveManager::AppendDisk(drive - 'A', isoDisks[ct]); } DriveManager::InitializeDrive(drive - 'A'); @@ -1073,7 +1163,7 @@ public: // Print status message (success) WriteOut(MSG_Get("MSCDEX_SUCCESS")); std::string tmp(paths[0]); - for (int i = 1; i < paths.size(); i++) { + for (i = 1; i < paths.size(); i++) { tmp += "; " + paths[i]; } WriteOut(MSG_Get("PROGRAM_MOUNT_STATUS_2"), drive, tmp.c_str()); @@ -1295,6 +1385,7 @@ void DOS_SetupPrograms(void) { ); MSG_Add("PROGRAM_BOOT_NOT_EXIST","Bootdisk file does not exist. Failing.\n"); MSG_Add("PROGRAM_BOOT_NOT_OPEN","Cannot open bootdisk file. Failing.\n"); + MSG_Add("PROGRAM_BOOT_WRITE_PROTECTED","Image file is read-only! Might create problems.\n"); MSG_Add("PROGRAM_BOOT_PRINT_ERROR","This command boots DOSBox from either a floppy or hard disk image.\n\n" "For this command, one can specify a succession of floppy disks swappable\n" "by pressing Ctrl-F4, and -l specifies the mounted drive to boot from. If\n" @@ -1321,6 +1412,10 @@ void DOS_SetupPrograms(void) { "For \033[33mhardrive\033[0m images: Must specify drive geometry for hard drives:\n" "bytes_per_sector, sectors_per_cylinder, heads_per_cylinder, cylinder_count.\n" "\033[34;1mIMGMOUNT drive-letter location-of-image -size bps,spc,hpc,cyl\033[0m\n"); + MSG_Add("PROGRAM_IMGMOUNT_INVALID_IMAGE","Could not load image file.\n" + "Check that the path is correct and the image is accessible.\n"); + MSG_Add("PROGRAM_IMGMOUNT_INVALID_GEOMETRY","Could not extract drive geometry from image.\n" + "Use parameter -size bps,spc,hpc,cyl to specify the geometry.\n"); MSG_Add("PROGRAM_IMGMOUNT_TYPE_UNSUPPORTED","Type \"%s\" is unsupported. Specify \"hdd\" or \"floppy\" or\"iso\".\n"); MSG_Add("PROGRAM_IMGMOUNT_FORMAT_UNSUPPORTED","Format \"%s\" is unsupported. Specify \"fat\" or \"iso\" or \"none\".\n"); MSG_Add("PROGRAM_IMGMOUNT_SPECIFY_FILE","Must specify file-image to mount.\n"); diff --git a/src/dos/dos_tables.cpp b/src/dos/dos_tables.cpp index b22a849..5c2b8b7 100644 --- a/src/dos/dos_tables.cpp +++ b/src/dos/dos_tables.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dos_tables.cpp,v 1.26 2007/01/08 20:36:53 qbix79 Exp $ */ +/* $Id: dos_tables.cpp,v 1.29 2007/07/20 18:53:52 qbix79 Exp $ */ #include "dosbox.h" #include "mem.h" @@ -40,10 +40,10 @@ RealPt DOS_TableLowCase; static Bitu call_casemap; -static Bit16u dos_memseg; +static Bit16u dos_memseg=DOS_PRIVATE_SEGMENT; Bit16u DOS_GetMemory(Bit16u pages) { - if (pages+dos_memseg>=0xd000) { + if (pages+dos_memseg>=DOS_PRIVATE_SEGMENT_END) { E_Exit("DOS:Not enough memory for internal tables"); } Bit16u page=dos_memseg; @@ -73,8 +73,7 @@ static Bit8u country_info[0x22] = { }; void DOS_SetupTables(void) { - dos_memseg=0xc800; - Bit16u seg,seg2;Bitu i; + Bit16u seg;Bitu i; dos.tables.mediaid=RealMake(DOS_GetMemory(4),0); dos.tables.tempdta=RealMake(DOS_GetMemory(4),0); dos.tables.tempdta_fcbdelete=RealMake(DOS_GetMemory(4),0); @@ -146,6 +145,10 @@ void DOS_SetupTables(void) { real_writew(seg,4,100); //File Table supports 100 files dos_infoblock.SetFCBTable(RealMake(seg,0)); + /* Create a fake DPB */ + dos.tables.dpb=DOS_GetMemory(2); + for(Bitu d=0;d<26;d++) real_writeb(dos.tables.dpb,d,d); + /* Create a fake disk buffer head */ seg=DOS_GetMemory(6); for (Bitu ct=0; ct<0x20; ct++) real_writeb(seg,ct,0); diff --git a/src/dos/drive_cache.cpp b/src/dos/drive_cache.cpp index bc3c924..89d618d 100644 --- a/src/dos/drive_cache.cpp +++ b/src/dos/drive_cache.cpp @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_cache.cpp,v 1.49 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: drive_cache.cpp,v 1.50 2007/06/12 20:22:08 c2woody Exp $ */ #include "drives.h" #include "dos_inc.h" @@ -242,7 +242,7 @@ void DOS_Drive_Cache::AddEntry(const char* path, bool checkExists) Bit32u i; // Check if there are any open search dir that are affected by this... if (dir) for (i=0; inextEntry)) + if ((dirSearch[i]==dir) && ((Bit32u)index<=dirSearch[i]->nextEntry)) dirSearch[i]->nextEntry++; } }; @@ -378,7 +378,7 @@ Bit16u DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) do { foundNr = curDir->longNameList[mid]->shortNr; mid++; - } while(midlongNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0)); + } while((Bitu)midlongNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0)); break; }; } diff --git a/src/dos/drive_fat.cpp b/src/dos/drive_fat.cpp index d7556aa..9ddad09 100644 --- a/src/dos/drive_fat.cpp +++ b/src/dos/drive_fat.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_fat.cpp,v 1.20 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: drive_fat.cpp,v 1.22 2007/06/14 08:23:46 qbix79 Exp $ */ #include #include @@ -399,8 +399,8 @@ bool fatDrive::getEntryName(char *fullname, char *entname) { return true; } -bool fatDrive::getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) { - Bit32u len = (Bit32u)strlen(filename); +bool fatDrive::getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry) { + size_t len = strlen(filename); char dirtoken[DOS_PATHLENGTH]; Bit32u currentClust = 0; @@ -408,6 +408,7 @@ bool fatDrive::getFileDirEntry(char * filename, direntry * useEntry, Bit32u * di char * findDir; char * findFile; strcpy(dirtoken,filename); + findFile=dirtoken; /* Skip if testing in root directory */ if ((len>0) && (filename[len-1]!='\\')) { @@ -794,7 +795,7 @@ bool fatDrive::FileCreate(DOS_File **file, char *name, Bit16u attributes) { bool fatDrive::FileExists(const char *name) { direntry fileEntry; Bit32u dummy1, dummy2; - if(!getFileDirEntry((char *)name, &fileEntry, &dummy1, &dummy2)) return false; + if(!getFileDirEntry(name, &fileEntry, &dummy1, &dummy2)) return false; return true; } diff --git a/src/dos/drive_iso.cpp b/src/dos/drive_iso.cpp index 907636e..77b628a 100644 --- a/src/dos/drive_iso.cpp +++ b/src/dos/drive_iso.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_iso.cpp,v 1.17 2007/01/21 16:21:22 c2woody Exp $ */ +/* $Id: drive_iso.cpp,v 1.20 2007/06/15 19:05:48 c2woody Exp $ */ #include #include @@ -52,10 +52,9 @@ isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u time = stat->time; date = stat->date; attr = stat->attr; - size = stat->size; fileBegin = offset; filePos = fileBegin; - fileEnd = fileBegin + size; + fileEnd = fileBegin + stat->size; cachedSector = -1; open = true; this->name = NULL; @@ -65,11 +64,11 @@ isoFile::isoFile(isoDrive *drive, const char *name, FileStat_Block *stat, Bit32u bool isoFile::Read(Bit8u *data, Bit16u *size) { if (filePos + *size > fileEnd) - *size = fileEnd - filePos; + *size = (Bit16u)(fileEnd - filePos); Bit16u nowSize = 0; int sector = filePos / ISO_FRAMESIZE; - Bit16u sectorPos = filePos % ISO_FRAMESIZE; + Bit16u sectorPos = (Bit16u)(filePos % ISO_FRAMESIZE); if (sector != cachedSector) { if (drive->readSector(buffer, sector)) cachedSector = sector; @@ -272,7 +271,7 @@ bool isoDrive::FindFirst(char *dir, DOS_DTA &dta, bool fcb_findfirst) } // get a directory iterator and save its id in the dta - dta.SetDirID(GetDirIterator(&de)); + dta.SetDirID((Bit16u)GetDirIterator(&de)); Bit8u attr; char pattern[ISO_MAXPATHNAME]; @@ -349,6 +348,7 @@ bool isoDrive::GetFileAttr(char *name, Bit16u *attr) bool success = lookup(&de, name); if (success) { *attr = DOS_ATTR_ARCHIVE | DOS_ATTR_READ_ONLY; + if (IS_HIDDEN(de.fileFlags)) *attr |= DOS_ATTR_HIDDEN; if (IS_DIR(de.fileFlags)) *attr |= DOS_ATTR_DIRECTORY; } return success; @@ -532,7 +532,7 @@ bool isoDrive :: loadImage() isoPVD pvd; readSector((Bit8u*)(&pvd), ISO_FIRST_VD); if (pvd.type != 1 || strncmp((char*)pvd.standardIdent, "CD001", 5) || pvd.version != 1) return false; - return (readDirEntry(&this->rootEntry, pvd.rootEntry)); + return (readDirEntry(&this->rootEntry, pvd.rootEntry)>0); } bool isoDrive :: lookup(isoDirEntry *de, const char *path) diff --git a/src/dos/drive_local.cpp b/src/dos/drive_local.cpp index b610673..22f52b4 100644 --- a/src/dos/drive_local.cpp +++ b/src/dos/drive_local.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drive_local.cpp,v 1.74 2007/01/09 17:44:20 c2woody Exp $ */ +/* $Id: drive_local.cpp,v 1.75 2007/06/13 07:25:14 qbix79 Exp $ */ #include #include @@ -517,7 +517,6 @@ localFile::localFile(const char* _name, FILE * handle) { } else { time=1;date=1; } - size=(Bit32u)temp_stat.st_size; attr=DOS_ATTR_ARCHIVE; last_action=NONE; read_only_medium=false; diff --git a/src/dos/drives.h b/src/dos/drives.h index 93cdc01..3bab27f 100644 --- a/src/dos/drives.h +++ b/src/dos/drives.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: drives.h,v 1.36 2007/01/21 16:21:22 c2woody Exp $ */ +/* $Id: drives.h,v 1.37 2007/06/14 08:23:46 qbix79 Exp $ */ #ifndef _DRIVES_H__ #define _DRIVES_H__ @@ -181,7 +181,7 @@ private: Bit32u getClustFirstSect(Bit32u clustNum); bool FindNextInternal(Bit32u dirClustNumber, DOS_DTA & dta, direntry *foundEntry); bool getDirClustNum(char * dir, Bit32u * clustNum, bool parDir); - bool getFileDirEntry(char * filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry); + bool getFileDirEntry(char const * const filename, direntry * useEntry, Bit32u * dirClust, Bit32u * subEntry); bool addDirectoryEntry(Bit32u dirClustNumber, direntry useEntry); void zeroOutCluster(Bit32u clustNumber); bool getEntryName(char *fullname, char *entname); diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 992e6b7..c80d82b 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: dosbox.cpp,v 1.115 2007/02/22 08:44:06 qbix79 Exp $ */ +/* $Id: dosbox.cpp,v 1.118 2007/07/02 20:06:59 c2woody Exp $ */ #include #include @@ -236,6 +236,10 @@ static void DOSBOX_RealInit(Section * sec) { ticksLocked = false; DOSBOX_SetLoop(&Normal_Loop); MSG_Init(section); + MSG_Add("CONFIGFILE_INTRO", + "# This is the configurationfile for DOSBox %s.\n" + "# Lines starting with a # are commentlines.\n" + "# They are used to (briefly) document the effect of each option.\n"); MAPPER_AddHandler(DOSBOX_UnlockSpeed, MK_f12, MMOD2,"speedlock","Speedlock"); svgaCard = SVGA_S3Trio; @@ -299,6 +303,8 @@ void DOSBOX_Init(void) { " Supported are none,normal2x,normal3x,advmame2x,advmame3x,hq2x,hq3x,\n" " 2xsai,super2xsai,supereagle,advinterp2x,advinterp3x,\n" " tv2x,tv3x,rgb2x,rgb3x,scan2x,scan3x.\n" + " If forced is appended (like scaler=hq2x forced), the scaler will be used\n" + " even if the result might not be desired.\n" ); secprop=control->AddSection_prop("cpu",&CPU_Init,true);//done @@ -420,7 +426,7 @@ void DOSBOX_Init(void) { "tandy -- Enable Tandy Sound System emulation (off,on,auto).\n" " For auto Tandysound emulation is present only if machine is set to tandy.\n" "tandyrate -- Sample rate of the Tandy 3-Voice generation.\n" - "disney -- Enable Disney Sound Source emulation.\n" + "disney -- Enable Disney Sound Source emulation. Covox Voice Master and Speech Thing compatible.\n" ); secprop=control->AddSection_prop("joystick",&BIOS_Init,false);//done diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index 0861366..2240713 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -64,11 +64,12 @@ public: next=handler_list; handler_list=this; }; - virtual bool Open(const char * conf) { return true; }; + virtual bool Open(const char * /*conf*/) { return true; }; virtual void Close(void) {}; - virtual void PlayMsg(Bit8u * msg) {}; - virtual void PlaySysex(Bit8u * sysex,Bitu len) {}; - virtual char * GetName(void) { return "none"; }; + virtual void PlayMsg(Bit8u * /*msg*/) {}; + virtual void PlaySysex(Bit8u * /*sysex*/,Bitu /*len*/) {}; + virtual const char * GetName(void) { return "none"; }; + virtual ~MidiHandler() { }; MidiHandler * next; }; @@ -199,7 +200,7 @@ getdefault: static MIDI* test; -void MIDI_Destroy(Section* sec){ +void MIDI_Destroy(Section* /*sec*/){ delete test; } void MIDI_Init(Section * sec) { diff --git a/src/gui/midi_alsa.h b/src/gui/midi_alsa.h index 0df45aa..0bc6b58 100644 --- a/src/gui/midi_alsa.h +++ b/src/gui/midi_alsa.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: midi_alsa.h,v 1.15 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: midi_alsa.h,v 1.16 2007/06/14 08:23:46 qbix79 Exp $ */ #define ALSA_PCM_OLD_HW_PARAMS_API #define ALSA_PCM_OLD_SW_PARAMS_API @@ -50,7 +50,7 @@ private: snd_seq_flush_output(seq_handle); } - int parse_addr(char *arg, int *client, int *port) { + int parse_addr(const char *arg, int *client, int *port) { char *p; if (isdigit(*arg)) { @@ -69,7 +69,7 @@ private: } public: MidiHandler_alsa() : MidiHandler() {}; - char* GetName(void) { return "alsa"; } + const char* GetName(void) { return "alsa"; } void PlaySysex(Bit8u * sysex,Bitu len) { snd_seq_ev_set_sysex(&ev, len, sysex); send_event(1); diff --git a/src/gui/midi_coreaudio.h b/src/gui/midi_coreaudio.h index 8fc0057..923f161 100644 --- a/src/gui/midi_coreaudio.h +++ b/src/gui/midi_coreaudio.h @@ -24,7 +24,7 @@ private: AudioUnit m_outputUnit; public: MidiHandler_coreaudio() : m_musicDevice(0), m_outputUnit(0) {} - char * GetName(void) { return "coreaudio"; } + const char * GetName(void) { return "coreaudio"; } bool Open(const char * conf) { int err; AudioUnitConnection auconnect; diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h index c4a945a..b4ae306 100644 --- a/src/gui/midi_oss.h +++ b/src/gui/midi_oss.h @@ -26,7 +26,7 @@ private: bool isOpen; public: MidiHandler_oss() : MidiHandler(),isOpen(false) {}; - char * GetName(void) { return "oss";}; + const char * GetName(void) { return "oss";}; bool Open(const char * conf) { char devname[512]; if (conf && conf[0]) safe_strncpy(devname,conf,512); diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index 6c4a893..cb7b0b7 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: midi_win32.h,v 1.13 2007/01/08 19:45:39 qbix79 Exp $ */ +/* $Id: midi_win32.h,v 1.14 2007/06/14 08:23:46 qbix79 Exp $ */ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN @@ -34,7 +34,7 @@ private: bool isOpen; public: MidiHandler_win32() : isOpen(false),MidiHandler() {}; - char * GetName(void) { return "win32";}; + const char * GetName(void) { return "win32";}; bool Open(const char * conf) { if (isOpen) return false; m_event = CreateEvent (NULL, true, true, NULL); diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 8f8117a..0c63c26 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: render.cpp,v 1.51 2007/02/03 13:00:16 harekiet Exp $ */ +/* $Id: render.cpp,v 1.54 2007/07/05 16:03:49 c2woody Exp $ */ #include #include @@ -282,7 +282,7 @@ static void RENDER_Reset( void ) { gfx_scalew = 1; gfx_scaleh = 1; } - if (dblh && dblw) { + if (dblh && dblw || (render.scale.forced && !dblh && !dblw)) { /* Initialize always working defaults */ if (render.scale.size == 2) simpleBlock = &ScaleNormal2x; @@ -291,7 +291,9 @@ static void RENDER_Reset( void ) { else simpleBlock = &ScaleNormal1x; /* Maybe override them */ +#if RENDER_USE_ADVANCED_SCALERS>0 switch (render.scale.op) { +#if RENDER_USE_ADVANCED_SCALERS>2 case scalerOpAdvInterp: if (render.scale.size == 2) complexBlock = &ScaleAdvInterp2x; @@ -322,6 +324,7 @@ static void RENDER_Reset( void ) { if (render.scale.size == 2) complexBlock = &Scale2xSaI; break; +#endif case scalerOpTV: if (render.scale.size == 2) simpleBlock = &ScaleTV2x; @@ -341,6 +344,7 @@ static void RENDER_Reset( void ) { simpleBlock = &ScaleScan3x; break; } +#endif } else if (dblw) { simpleBlock = &ScaleNormalDw; } else if (dblh) { @@ -351,10 +355,14 @@ forcenormal: simpleBlock = &ScaleNormal1x; } if (complexBlock) { +#if RENDER_USE_ADVANCED_SCALERS>1 if ((width >= SCALER_COMPLEXWIDTH - 16) || height >= SCALER_COMPLEXHEIGHT - 16) { LOG_MSG("Scaler can't handle this resolution, going back to normal"); goto forcenormal; } +#else + goto forcenormal; +#endif gfx_flags = complexBlock->gfxFlags; xscale = complexBlock->xscale; yscale = complexBlock->yscale; @@ -423,18 +431,24 @@ forcenormal: E_Exit("Failed to create a rendering output"); ScalerLineBlock_t *lineBlock; if (gfx_flags & GFX_HARDWARE) { +#if RENDER_USE_ADVANCED_SCALERS>1 if (complexBlock) { lineBlock = &ScalerCache; render.scale.complexHandler = complexBlock->Linear[ render.scale.outMode ]; - } else { + } else +#endif + { render.scale.complexHandler = 0; lineBlock = &simpleBlock->Linear; } } else { +#if RENDER_USE_ADVANCED_SCALERS>1 if (complexBlock) { lineBlock = &ScalerCache; render.scale.complexHandler = complexBlock->Random[ render.scale.outMode ]; - } else { + } else +#endif + { render.scale.complexHandler = 0; lineBlock = &simpleBlock->Random; } @@ -548,6 +562,8 @@ void RENDER_Init(Section * sec) { //For restarting the renderer. static bool running = false; bool aspect = render.aspect; + Bitu scalersize = render.scale.size; + bool scalerforced = render.scale.forced; scalerOperation_t scaleOp = render.scale.op; render.pal.first=256; @@ -555,15 +571,31 @@ void RENDER_Init(Section * sec) { render.aspect=section->Get_bool("aspect"); render.frameskip.max=section->Get_int("frameskip"); render.frameskip.count=0; - const char * scaler;std::string cline; + const char * scaler; + std::string cline; + std::string scaler_str; if (control->cmdline->FindString("-scaler",cline,false)) { scaler=cline.c_str(); + render.scale.forced=false; + } else if (control->cmdline->FindString("-forcescaler",cline,false)) { + scaler=cline.c_str(); + render.scale.forced=true; } else { - scaler=section->Get_string("scaler"); + CommandLine cmd(0,section->Get_string("scaler")); + cmd.FindCommand(1,scaler_str); + scaler=scaler_str.c_str(); + render.scale.forced=false; + if (cmd.GetCount()>1) { + std::string str; + if (cmd.FindCommand(2,str)) { + if (str=="forced") render.scale.forced=true; + } + } } if (!strcasecmp(scaler,"none")) { render.scale.op = scalerOpNormal;render.scale.size = 1; } else if (!strcasecmp(scaler,"normal2x")) { render.scale.op = scalerOpNormal;render.scale.size = 2; } else if (!strcasecmp(scaler,"normal3x")) { render.scale.op = scalerOpNormal;render.scale.size = 3; } +#if RENDER_USE_ADVANCED_SCALERS>2 else if (!strcasecmp(scaler,"advmame2x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 2; } else if (!strcasecmp(scaler,"advmame3x")) { render.scale.op = scalerOpAdvMame;render.scale.size = 3; } else if (!strcasecmp(scaler,"advinterp2x")) { render.scale.op = scalerOpAdvInterp;render.scale.size = 2; } @@ -573,19 +605,24 @@ void RENDER_Init(Section * sec) { else if (!strcasecmp(scaler,"2xsai")) { render.scale.op = scalerOpSaI;render.scale.size = 2; } else if (!strcasecmp(scaler,"super2xsai")) { render.scale.op = scalerOpSuperSaI;render.scale.size = 2; } else if (!strcasecmp(scaler,"supereagle")) { render.scale.op = scalerOpSuperEagle;render.scale.size = 2; } +#endif +#if RENDER_USE_ADVANCED_SCALERS>0 else if (!strcasecmp(scaler,"tv2x")) { render.scale.op = scalerOpTV;render.scale.size = 2; } else if (!strcasecmp(scaler,"tv3x")) { render.scale.op = scalerOpTV;render.scale.size = 3; } else if (!strcasecmp(scaler,"rgb2x")){ render.scale.op = scalerOpRGB;render.scale.size = 2; } else if (!strcasecmp(scaler,"rgb3x")){ render.scale.op = scalerOpRGB;render.scale.size = 3; } else if (!strcasecmp(scaler,"scan2x")){ render.scale.op = scalerOpScan;render.scale.size = 2; } else if (!strcasecmp(scaler,"scan3x")){ render.scale.op = scalerOpScan;render.scale.size = 3; } +#endif else { render.scale.op = scalerOpNormal;render.scale.size = 1; LOG_MSG("Illegal scaler type %s,falling back to normal.",scaler); } //If something changed that needs a ReInit - if(running && (render.aspect != aspect || render.scale.op != scaleOp)) + if(running &&((render.aspect != aspect) || (render.scale.op != scaleOp) || + (render.scale.size != scalersize) || (render.scale.forced != scalerforced) || + render.scale.forced)) RENDER_CallBack( GFX_CallBackReset ); if(!running) render.updating=true; diff --git a/src/gui/render_scalers.cpp b/src/gui/render_scalers.cpp index ad6ae67..c20d266 100644 --- a/src/gui/render_scalers.cpp +++ b/src/gui/render_scalers.cpp @@ -36,7 +36,9 @@ static union { } scalerWriteCache; //scalerFrameCache_t scalerFrameCache; scalerSourceCache_t scalerSourceCache; +#if RENDER_USE_ADVANCED_SCALERS>1 scalerChangeCache_t scalerChangeCache; +#endif #define _conc2(A,B) A ## B #define _conc3(A,B,C) A ## B ## C @@ -159,207 +161,223 @@ static INLINE void ScalerAddLines( Bitu changed, Bitu count ) { #undef DBPP +#if RENDER_USE_ADVANCED_SCALERS>1 ScalerLineBlock_t ScalerCache = { - Cache_8_8, Cache_8_15, Cache_8_16, Cache_8_32, - 0, Cache_15_15, Cache_15_16, Cache_15_32, - 0, Cache_16_15, Cache_16_16, Cache_16_32, - 0, Cache_32_15, Cache_32_16, Cache_32_32, - Cache_8_8, Cache_9_15, Cache_9_16, Cache_9_32, +{ Cache_8_8, Cache_8_15 , Cache_8_16 , Cache_8_32 }, +{ 0, Cache_15_15, Cache_15_16, Cache_15_32}, +{ 0, Cache_16_15, Cache_16_16, Cache_16_32}, +{ 0, Cache_32_15, Cache_32_16, Cache_32_32}, +{ Cache_8_8, Cache_9_15 , Cache_9_16 , Cache_9_32 } }; +#endif ScalerSimpleBlock_t ScaleNormal1x = { "Normal", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 1,1, - Normal1x_8_8_L, Normal1x_8_15_L, Normal1x_8_16_L, Normal1x_8_32_L, - 0, Normal1x_15_15_L, Normal1x_15_16_L, Normal1x_15_32_L, - 0, Normal1x_16_15_L, Normal1x_16_16_L, Normal1x_16_32_L, - 0, Normal1x_32_15_L, Normal1x_32_16_L, Normal1x_32_32_L, - Normal1x_8_8_L, Normal1x_9_15_L, Normal1x_9_16_L, Normal1x_9_32_L, - Normal1x_8_8_R, Normal1x_8_15_R, Normal1x_8_16_R, Normal1x_8_32_R, - 0, Normal1x_15_15_R, Normal1x_15_16_R, Normal1x_15_32_R, - 0, Normal1x_16_15_R, Normal1x_16_16_R, Normal1x_16_32_R, - 0, Normal1x_32_15_R, Normal1x_32_16_R, Normal1x_32_32_R, - Normal1x_8_8_R, Normal1x_9_15_R, Normal1x_9_16_R, Normal1x_9_32_R, -}; + 1,1,{ +{ Normal1x_8_8_L, Normal1x_8_15_L , Normal1x_8_16_L , Normal1x_8_32_L }, +{ 0, Normal1x_15_15_L, Normal1x_15_16_L, Normal1x_15_32_L}, +{ 0, Normal1x_16_15_L, Normal1x_16_16_L, Normal1x_16_32_L}, +{ 0, Normal1x_32_15_L, Normal1x_32_16_L, Normal1x_32_32_L}, +{ Normal1x_8_8_L, Normal1x_9_15_L , Normal1x_9_16_L , Normal1x_9_32_L } +},{ +{ Normal1x_8_8_R, Normal1x_8_15_R , Normal1x_8_16_R , Normal1x_8_32_R }, +{ 0, Normal1x_15_15_R, Normal1x_15_16_R, Normal1x_15_32_R}, +{ 0, Normal1x_16_15_R, Normal1x_16_16_R, Normal1x_16_32_R}, +{ 0, Normal1x_32_15_R, Normal1x_32_16_R, Normal1x_32_32_R}, +{ Normal1x_8_8_R, Normal1x_9_15_R , Normal1x_9_16_R , Normal1x_9_32_R } +}}; ScalerSimpleBlock_t ScaleNormalDw = { "Normal", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 2,1, - NormalDw_8_8_L, NormalDw_8_15_L, NormalDw_8_16_L, NormalDw_8_32_L, - 0, NormalDw_15_15_L, NormalDw_15_16_L, NormalDw_15_32_L, - 0, NormalDw_16_15_L, NormalDw_16_16_L, NormalDw_16_32_L, - 0, NormalDw_32_15_L, NormalDw_32_16_L, NormalDw_32_32_L, - NormalDw_8_8_L, NormalDw_9_15_L, NormalDw_9_16_L, NormalDw_9_32_L, - NormalDw_8_8_R, NormalDw_8_15_R, NormalDw_8_16_R, NormalDw_8_32_R, - 0, NormalDw_15_15_R, NormalDw_15_16_R, NormalDw_15_32_R, - 0, NormalDw_16_15_R, NormalDw_16_16_R, NormalDw_16_32_R, - 0, NormalDw_32_15_R, NormalDw_32_16_R, NormalDw_32_32_R, - NormalDw_8_8_R, NormalDw_9_15_R, NormalDw_9_16_R, NormalDw_9_32_R, -}; + 2,1,{ +{ NormalDw_8_8_L, NormalDw_8_15_L , NormalDw_8_16_L , NormalDw_8_32_L }, +{ 0, NormalDw_15_15_L, NormalDw_15_16_L, NormalDw_15_32_L}, +{ 0, NormalDw_16_15_L, NormalDw_16_16_L, NormalDw_16_32_L}, +{ 0, NormalDw_32_15_L, NormalDw_32_16_L, NormalDw_32_32_L}, +{ NormalDw_8_8_L, NormalDw_9_15_L , NormalDw_9_16_L , NormalDw_9_32_L } +},{ +{ NormalDw_8_8_R, NormalDw_8_15_R , NormalDw_8_16_R , NormalDw_8_32_R }, +{ 0, NormalDw_15_15_R, NormalDw_15_16_R, NormalDw_15_32_R}, +{ 0, NormalDw_16_15_R, NormalDw_16_16_R, NormalDw_16_32_R}, +{ 0, NormalDw_32_15_R, NormalDw_32_16_R, NormalDw_32_32_R}, +{ NormalDw_8_8_R, NormalDw_9_15_R , NormalDw_9_16_R , NormalDw_9_32_R } +}}; ScalerSimpleBlock_t ScaleNormalDh = { "Normal", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 1,2, - NormalDh_8_8_L, NormalDh_8_15_L, NormalDh_8_16_L, NormalDh_8_32_L, - 0, NormalDh_15_15_L, NormalDh_15_16_L, NormalDh_15_32_L, - 0, NormalDh_16_15_L, NormalDh_16_16_L, NormalDh_16_32_L, - 0, NormalDh_32_15_L, NormalDh_32_16_L, NormalDh_32_32_L, - NormalDh_8_8_L, NormalDh_9_15_L, NormalDh_9_16_L, NormalDh_9_32_L, - NormalDh_8_8_R, NormalDh_8_15_R, NormalDh_8_16_R, NormalDh_8_32_R, - 0, NormalDh_15_15_R, NormalDh_15_16_R, NormalDh_15_32_R, - 0, NormalDh_16_15_R, NormalDh_16_16_R, NormalDh_16_32_R, - 0, NormalDh_32_15_R, NormalDh_32_16_R, NormalDh_32_32_R, - NormalDh_8_8_R, NormalDh_9_15_R, NormalDh_9_16_R, NormalDh_9_32_R, -}; + 1,2,{ +{ NormalDh_8_8_L, NormalDh_8_15_L , NormalDh_8_16_L , NormalDh_8_32_L }, +{ 0, NormalDh_15_15_L, NormalDh_15_16_L, NormalDh_15_32_L}, +{ 0, NormalDh_16_15_L, NormalDh_16_16_L, NormalDh_16_32_L}, +{ 0, NormalDh_32_15_L, NormalDh_32_16_L, NormalDh_32_32_L}, +{ NormalDh_8_8_L, NormalDh_9_15_L , NormalDh_9_16_L , NormalDh_9_32_L } +},{ +{ NormalDh_8_8_R, NormalDh_8_15_R , NormalDh_8_16_R , NormalDh_8_32_R }, +{ 0, NormalDh_15_15_R, NormalDh_15_16_R, NormalDh_15_32_R}, +{ 0, NormalDh_16_15_R, NormalDh_16_16_R, NormalDh_16_32_R}, +{ 0, NormalDh_32_15_R, NormalDh_32_16_R, NormalDh_32_32_R}, +{ NormalDh_8_8_R, NormalDh_9_15_R , NormalDh_9_16_R , NormalDh_9_32_R } +}}; ScalerSimpleBlock_t ScaleNormal2x = { "Normal2x", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 2,2, - Normal2x_8_8_L, Normal2x_8_15_L, Normal2x_8_16_L, Normal2x_8_32_L, - 0, Normal2x_15_15_L, Normal2x_15_16_L, Normal2x_15_32_L, - 0, Normal2x_16_15_L, Normal2x_16_16_L, Normal2x_16_32_L, - 0, Normal2x_32_15_L, Normal2x_32_16_L, Normal2x_32_32_L, - Normal2x_8_8_L, Normal2x_9_15_L, Normal2x_9_16_L, Normal2x_9_32_L, - Normal2x_8_8_R, Normal2x_8_15_R, Normal2x_8_16_R, Normal2x_8_32_R, - 0, Normal2x_15_15_R, Normal2x_15_16_R, Normal2x_15_32_R, - 0, Normal2x_16_15_R, Normal2x_16_16_R, Normal2x_16_32_R, - 0, Normal2x_32_15_R, Normal2x_32_16_R, Normal2x_32_32_R, - Normal2x_8_8_R, Normal2x_9_15_R, Normal2x_9_16_R, Normal2x_9_32_R, -}; + 2,2,{ +{ Normal2x_8_8_L, Normal2x_8_15_L, Normal2x_8_16_L, Normal2x_8_32_L }, +{ 0, Normal2x_15_15_L, Normal2x_15_16_L, Normal2x_15_32_L}, +{ 0, Normal2x_16_15_L, Normal2x_16_16_L, Normal2x_16_32_L}, +{ 0, Normal2x_32_15_L, Normal2x_32_16_L, Normal2x_32_32_L}, +{ Normal2x_8_8_L, Normal2x_9_15_L , Normal2x_9_16_L, Normal2x_9_32_L } +},{ +{ Normal2x_8_8_R, Normal2x_8_15_R , Normal2x_8_16_R, Normal2x_8_32_R }, +{ 0, Normal2x_15_15_R, Normal2x_15_16_R, Normal2x_15_32_R}, +{ 0, Normal2x_16_15_R, Normal2x_16_16_R, Normal2x_16_32_R}, +{ 0, Normal2x_32_15_R, Normal2x_32_16_R, Normal2x_32_32_R}, +{ Normal2x_8_8_R, Normal2x_9_15_R , Normal2x_9_16_R, Normal2x_9_32_R }, +}}; ScalerSimpleBlock_t ScaleNormal3x = { "Normal3x", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, - 3,3, - Normal3x_8_8_L, Normal3x_8_15_L, Normal3x_8_16_L, Normal3x_8_32_L, - 0, Normal3x_15_15_L, Normal3x_15_16_L, Normal3x_15_32_L, - 0, Normal3x_16_15_L, Normal3x_16_16_L, Normal3x_16_32_L, - 0, Normal3x_32_15_L, Normal3x_32_16_L, Normal3x_32_32_L, - Normal3x_8_8_L, Normal3x_9_15_L, Normal3x_9_16_L, Normal3x_9_32_L, - Normal3x_8_8_R, Normal3x_8_15_R, Normal3x_8_16_R, Normal3x_8_32_R, - 0, Normal3x_15_15_R, Normal3x_15_16_R, Normal3x_15_32_R, - 0, Normal3x_16_15_R, Normal3x_16_16_R, Normal3x_16_32_R, - 0, Normal3x_32_15_R, Normal3x_32_16_R, Normal3x_32_32_R, - Normal3x_8_8_R, Normal3x_9_15_R, Normal3x_9_16_R, Normal3x_9_32_R, -}; + 3,3,{ +{ Normal3x_8_8_L, Normal3x_8_15_L , Normal3x_8_16_L , Normal3x_8_32_L }, +{ 0, Normal3x_15_15_L, Normal3x_15_16_L, Normal3x_15_32_L}, +{ 0, Normal3x_16_15_L, Normal3x_16_16_L, Normal3x_16_32_L}, +{ 0, Normal3x_32_15_L, Normal3x_32_16_L, Normal3x_32_32_L}, +{ Normal3x_8_8_L, Normal3x_9_15_L , Normal3x_9_16_L , Normal3x_9_32_L } +},{ +{ Normal3x_8_8_R, Normal3x_8_15_R , Normal3x_8_16_R , Normal3x_8_32_R }, +{ 0, Normal3x_15_15_R, Normal3x_15_16_R, Normal3x_15_32_R}, +{ 0, Normal3x_16_15_R, Normal3x_16_16_R, Normal3x_16_32_R}, +{ 0, Normal3x_32_15_R, Normal3x_32_16_R, Normal3x_32_32_R}, +{ Normal3x_8_8_R, Normal3x_9_15_R , Normal3x_9_16_R , Normal3x_9_32_R } +}}; +#if RENDER_USE_ADVANCED_SCALERS>0 ScalerSimpleBlock_t ScaleTV2x = { "TV2x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, - 0, TV2x_8_15_L, TV2x_8_16_L, TV2x_8_32_L, - 0, TV2x_15_15_L, TV2x_15_16_L, TV2x_15_32_L, - 0, TV2x_16_15_L, TV2x_16_16_L, TV2x_16_32_L, - 0, TV2x_32_15_L, TV2x_32_16_L, TV2x_32_32_L, - 0, TV2x_9_15_L, TV2x_9_16_L, TV2x_9_32_L, - 0, TV2x_8_15_R, TV2x_8_16_R, TV2x_8_32_R, - 0, TV2x_15_15_R, TV2x_15_16_R, TV2x_15_32_R, - 0, TV2x_16_15_R, TV2x_16_16_R, TV2x_16_32_R, - 0, TV2x_32_15_R, TV2x_32_16_R, TV2x_32_32_R, - 0, TV2x_9_15_R, TV2x_9_16_R, TV2x_9_32_R, -}; + 2,2,{ +{ 0, TV2x_8_15_L , TV2x_8_16_L , TV2x_8_32_L }, +{ 0, TV2x_15_15_L, TV2x_15_16_L, TV2x_15_32_L}, +{ 0, TV2x_16_15_L, TV2x_16_16_L, TV2x_16_32_L}, +{ 0, TV2x_32_15_L, TV2x_32_16_L, TV2x_32_32_L}, +{ 0, TV2x_9_15_L , TV2x_9_16_L , TV2x_9_32_L } +},{ +{ 0, TV2x_8_15_R , TV2x_8_16_R , TV2x_8_32_R }, +{ 0, TV2x_15_15_R, TV2x_15_16_R, TV2x_15_32_R}, +{ 0, TV2x_16_15_R, TV2x_16_16_R, TV2x_16_32_R}, +{ 0, TV2x_32_15_R, TV2x_32_16_R, TV2x_32_32_R}, +{ 0, TV2x_9_15_R , TV2x_9_16_R , TV2x_9_32_R } +}}; ScalerSimpleBlock_t ScaleTV3x = { "TV3x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3, - 0, TV3x_8_15_L, TV3x_8_16_L, TV3x_8_32_L, - 0, TV3x_15_15_L, TV3x_15_16_L, TV3x_15_32_L, - 0, TV3x_16_15_L, TV3x_16_16_L, TV3x_16_32_L, - 0, TV3x_32_15_L, TV3x_32_16_L, TV3x_32_32_L, - 0, TV3x_9_15_L, TV3x_9_16_L, TV3x_9_32_L, - 0, TV3x_8_15_R, TV3x_8_16_R, TV3x_8_32_R, - 0, TV3x_15_15_R, TV3x_15_16_R, TV3x_15_32_R, - 0, TV3x_16_15_R, TV3x_16_16_R, TV3x_16_32_R, - 0, TV3x_32_15_R, TV3x_32_16_R, TV3x_32_32_R, - 0, TV3x_9_15_R, TV3x_9_16_R, TV3x_9_32_R, -}; + 3,3,{ +{ 0, TV3x_8_15_L , TV3x_8_16_L , TV3x_8_32_L }, +{ 0, TV3x_15_15_L, TV3x_15_16_L, TV3x_15_32_L}, +{ 0, TV3x_16_15_L, TV3x_16_16_L, TV3x_16_32_L}, +{ 0, TV3x_32_15_L, TV3x_32_16_L, TV3x_32_32_L}, +{ 0, TV3x_9_15_L , TV3x_9_16_L , TV3x_9_32_L } +},{ +{ 0, TV3x_8_15_R , TV3x_8_16_R , TV3x_8_32_R }, +{ 0, TV3x_15_15_R, TV3x_15_16_R, TV3x_15_32_R}, +{ 0, TV3x_16_15_R, TV3x_16_16_R, TV3x_16_32_R}, +{ 0, TV3x_32_15_R, TV3x_32_16_R, TV3x_32_32_R}, +{ 0, TV3x_9_15_R , TV3x_9_16_R , TV3x_9_32_R } +}}; ScalerSimpleBlock_t ScaleScan2x = { "Scan2x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, - 0, Scan2x_8_15_L, Scan2x_8_16_L, Scan2x_8_32_L, - 0, Scan2x_15_15_L, Scan2x_15_16_L, Scan2x_15_32_L, - 0, Scan2x_16_15_L, Scan2x_16_16_L, Scan2x_16_32_L, - 0, Scan2x_32_15_L, Scan2x_32_16_L, Scan2x_32_32_L, - 0, Scan2x_9_15_L, Scan2x_9_16_L, Scan2x_9_32_L, - 0, Scan2x_8_15_R, Scan2x_8_16_R, Scan2x_8_32_R, - 0, Scan2x_15_15_R, Scan2x_15_16_R, Scan2x_15_32_R, - 0, Scan2x_16_15_R, Scan2x_16_16_R, Scan2x_16_32_R, - 0, Scan2x_32_15_R, Scan2x_32_16_R, Scan2x_32_32_R, - 0, Scan2x_9_15_R, Scan2x_9_16_R, Scan2x_9_32_R, -}; + 2,2,{ +{ 0, Scan2x_8_15_L , Scan2x_8_16_L , Scan2x_8_32_L }, +{ 0, Scan2x_15_15_L, Scan2x_15_16_L, Scan2x_15_32_L}, +{ 0, Scan2x_16_15_L, Scan2x_16_16_L, Scan2x_16_32_L}, +{ 0, Scan2x_32_15_L, Scan2x_32_16_L, Scan2x_32_32_L}, +{ 0, Scan2x_9_15_L , Scan2x_9_16_L , Scan2x_9_32_L } +},{ +{ 0, Scan2x_8_15_R , Scan2x_8_16_R , Scan2x_8_32_R }, +{ 0, Scan2x_15_15_R, Scan2x_15_16_R, Scan2x_15_32_R}, +{ 0, Scan2x_16_15_R, Scan2x_16_16_R, Scan2x_16_32_R}, +{ 0, Scan2x_32_15_R, Scan2x_32_16_R, Scan2x_32_32_R}, +{ 0, Scan2x_9_15_R , Scan2x_9_16_R , Scan2x_9_32_R } +}}; ScalerSimpleBlock_t ScaleScan3x = { "Scan3x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3, - 0, Scan3x_8_15_L, Scan3x_8_16_L, Scan3x_8_32_L, - 0, Scan3x_15_15_L, Scan3x_15_16_L, Scan3x_15_32_L, - 0, Scan3x_16_15_L, Scan3x_16_16_L, Scan3x_16_32_L, - 0, Scan3x_32_15_L, Scan3x_32_16_L, Scan3x_32_32_L, - 0, Scan3x_9_15_L, Scan3x_9_16_L, Scan3x_9_32_L, - 0, Scan3x_8_15_R, Scan3x_8_16_R, Scan3x_8_32_R, - 0, Scan3x_15_15_R, Scan3x_15_16_R, Scan3x_15_32_R, - 0, Scan3x_16_15_R, Scan3x_16_16_R, Scan3x_16_32_R, - 0, Scan3x_32_15_R, Scan3x_32_16_R, Scan3x_32_32_R, - 0, Scan3x_9_15_R, Scan3x_9_16_R, Scan3x_9_32_R, -}; + 3,3,{ +{ 0, Scan3x_8_15_L , Scan3x_8_16_L , Scan3x_8_32_L }, +{ 0, Scan3x_15_15_L, Scan3x_15_16_L, Scan3x_15_32_L}, +{ 0, Scan3x_16_15_L, Scan3x_16_16_L, Scan3x_16_32_L}, +{ 0, Scan3x_32_15_L, Scan3x_32_16_L, Scan3x_32_32_L}, +{ 0, Scan3x_9_15_L , Scan3x_9_16_L , Scan3x_9_32_L }, +},{ +{ 0, Scan3x_8_15_R , Scan3x_8_16_R , Scan3x_8_32_R }, +{ 0, Scan3x_15_15_R, Scan3x_15_16_R, Scan3x_15_32_R}, +{ 0, Scan3x_16_15_R, Scan3x_16_16_R, Scan3x_16_32_R}, +{ 0, Scan3x_32_15_R, Scan3x_32_16_R, Scan3x_32_32_R}, +{ 0, Scan3x_9_15_R , Scan3x_9_16_R , Scan3x_9_32_R } +}}; ScalerSimpleBlock_t ScaleRGB2x = { "RGB2x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 2,2, - 0, RGB2x_8_15_L, RGB2x_8_16_L, RGB2x_8_32_L, - 0, RGB2x_15_15_L, RGB2x_15_16_L, RGB2x_15_32_L, - 0, RGB2x_16_15_L, RGB2x_16_16_L, RGB2x_16_32_L, - 0, RGB2x_32_15_L, RGB2x_32_16_L, RGB2x_32_32_L, - 0, RGB2x_9_15_L, RGB2x_9_16_L, RGB2x_9_32_L, - 0, RGB2x_8_15_R, RGB2x_8_16_R, RGB2x_8_32_R, - 0, RGB2x_15_15_R, RGB2x_15_16_R, RGB2x_15_32_R, - 0, RGB2x_16_15_R, RGB2x_16_16_R, RGB2x_16_32_R, - 0, RGB2x_32_15_R, RGB2x_32_16_R, RGB2x_32_32_R, - 0, RGB2x_9_15_R, RGB2x_9_16_R, RGB2x_9_32_R, -}; + 2,2,{ +{ 0, RGB2x_8_15_L , RGB2x_8_16_L , RGB2x_8_32_L }, +{ 0, RGB2x_15_15_L, RGB2x_15_16_L, RGB2x_15_32_L}, +{ 0, RGB2x_16_15_L, RGB2x_16_16_L, RGB2x_16_32_L}, +{ 0, RGB2x_32_15_L, RGB2x_32_16_L, RGB2x_32_32_L}, +{ 0, RGB2x_9_15_L , RGB2x_9_16_L , RGB2x_9_32_L } +},{ +{ 0, RGB2x_8_15_R , RGB2x_8_16_R , RGB2x_8_32_R }, +{ 0, RGB2x_15_15_R, RGB2x_15_16_R, RGB2x_15_32_R}, +{ 0, RGB2x_16_15_R, RGB2x_16_16_R, RGB2x_16_32_R}, +{ 0, RGB2x_32_15_R, RGB2x_32_16_R, RGB2x_32_32_R}, +{ 0, RGB2x_9_15_R , RGB2x_9_16_R , RGB2x_9_32_R } +}}; ScalerSimpleBlock_t ScaleRGB3x = { "RGB3x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, - 3,3, - 0, RGB3x_8_15_L, RGB3x_8_16_L, RGB3x_8_32_L, - 0, RGB3x_15_15_L, RGB3x_15_16_L, RGB3x_15_32_L, - 0, RGB3x_16_15_L, RGB3x_16_16_L, RGB3x_16_32_L, - 0, RGB3x_32_15_L, RGB3x_32_16_L, RGB3x_32_32_L, - 0, RGB3x_9_15_L, RGB3x_9_16_L, RGB3x_9_32_L, - 0, RGB3x_8_15_R, RGB3x_8_16_R, RGB3x_8_32_R, - 0, RGB3x_15_15_R, RGB3x_15_16_R, RGB3x_15_32_R, - 0, RGB3x_16_15_R, RGB3x_16_16_R, RGB3x_16_32_R, - 0, RGB3x_32_15_R, RGB3x_32_16_R, RGB3x_32_32_R, - 0, RGB3x_9_15_R, RGB3x_9_16_R, RGB3x_9_32_R, -}; + 3,3,{ +{ 0, RGB3x_8_15_L , RGB3x_8_16_L , RGB3x_8_32_L }, +{ 0, RGB3x_15_15_L, RGB3x_15_16_L, RGB3x_15_32_L}, +{ 0, RGB3x_16_15_L, RGB3x_16_16_L, RGB3x_16_32_L}, +{ 0, RGB3x_32_15_L, RGB3x_32_16_L, RGB3x_32_32_L}, +{ 0, RGB3x_9_15_L , RGB3x_9_16_L , RGB3x_9_32_L } +},{ +{ 0, RGB3x_8_15_R , RGB3x_8_16_R , RGB3x_8_32_R }, +{ 0, RGB3x_15_15_R, RGB3x_15_16_R, RGB3x_15_32_R}, +{ 0, RGB3x_16_15_R, RGB3x_16_16_R, RGB3x_16_32_R}, +{ 0, RGB3x_32_15_R, RGB3x_32_16_R, RGB3x_32_32_R}, +{ 0, RGB3x_9_15_R , RGB3x_9_16_R , RGB3x_9_32_R } +}}; +#endif /* Complex scalers */ +#if RENDER_USE_ADVANCED_SCALERS>2 ScalerComplexBlock_t ScaleAdvMame2x ={ "AdvMame2x", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, 2,2, - AdvMame2x_8_L,AdvMame2x_16_L,AdvMame2x_16_L,AdvMame2x_32_L, - AdvMame2x_8_R,AdvMame2x_16_R,AdvMame2x_16_R,AdvMame2x_32_R +{ AdvMame2x_8_L,AdvMame2x_16_L,AdvMame2x_16_L,AdvMame2x_32_L}, +{ AdvMame2x_8_R,AdvMame2x_16_R,AdvMame2x_16_R,AdvMame2x_32_R} }; ScalerComplexBlock_t ScaleAdvMame3x = { "AdvMame3x", GFX_CAN_8|GFX_CAN_15|GFX_CAN_16|GFX_CAN_32, 3,3, - AdvMame3x_8_L,AdvMame3x_16_L,AdvMame3x_16_L,AdvMame3x_32_L, - AdvMame3x_8_R,AdvMame3x_16_R,AdvMame3x_16_R,AdvMame3x_32_R +{ AdvMame3x_8_L,AdvMame3x_16_L,AdvMame3x_16_L,AdvMame3x_32_L}, +{ AdvMame3x_8_R,AdvMame3x_16_R,AdvMame3x_16_R,AdvMame3x_32_R} }; /* These need specific 15bpp versions */ @@ -367,56 +385,56 @@ ScalerComplexBlock_t ScaleHQ2x ={ "HQ2x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 2,2, - 0,HQ2x_16_L,HQ2x_16_L,HQ2x_32_L, - 0,HQ2x_16_R,HQ2x_16_R,HQ2x_32_R +{ 0,HQ2x_16_L,HQ2x_16_L,HQ2x_32_L}, +{ 0,HQ2x_16_R,HQ2x_16_R,HQ2x_32_R} }; ScalerComplexBlock_t ScaleHQ3x ={ "HQ3x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 3,3, - 0,HQ3x_16_L,HQ3x_16_L,HQ3x_32_L, - 0,HQ3x_16_R,HQ3x_16_R,HQ3x_32_R +{ 0,HQ3x_16_L,HQ3x_16_L,HQ3x_32_L}, +{ 0,HQ3x_16_R,HQ3x_16_R,HQ3x_32_R} }; ScalerComplexBlock_t ScaleSuper2xSaI ={ "Super2xSaI", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 2,2, - 0,Super2xSaI_16_L,Super2xSaI_16_L,Super2xSaI_32_L, - 0,Super2xSaI_16_R,Super2xSaI_16_R,Super2xSaI_32_R +{ 0,Super2xSaI_16_L,Super2xSaI_16_L,Super2xSaI_32_L}, +{ 0,Super2xSaI_16_R,Super2xSaI_16_R,Super2xSaI_32_R} }; ScalerComplexBlock_t Scale2xSaI ={ "2xSaI", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 2,2, - 0,_2xSaI_16_L,_2xSaI_16_L,_2xSaI_32_L, - 0,_2xSaI_16_R,_2xSaI_16_R,_2xSaI_32_R +{ 0,_2xSaI_16_L,_2xSaI_16_L,_2xSaI_32_L}, +{ 0,_2xSaI_16_R,_2xSaI_16_R,_2xSaI_32_R} }; ScalerComplexBlock_t ScaleSuperEagle ={ "SuperEagle", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 2,2, - 0,SuperEagle_16_L,SuperEagle_16_L,SuperEagle_32_L, - 0,SuperEagle_16_R,SuperEagle_16_R,SuperEagle_32_R +{ 0,SuperEagle_16_L,SuperEagle_16_L,SuperEagle_32_L}, +{ 0,SuperEagle_16_R,SuperEagle_16_R,SuperEagle_32_R} }; ScalerComplexBlock_t ScaleAdvInterp2x = { "AdvInterp2x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 2,2, - 0,AdvInterp2x_15_L,AdvInterp2x_16_L,AdvInterp2x_32_L, - 0,AdvInterp2x_15_R,AdvInterp2x_16_R,AdvInterp2x_32_R +{ 0,AdvInterp2x_15_L,AdvInterp2x_16_L,AdvInterp2x_32_L}, +{ 0,AdvInterp2x_15_R,AdvInterp2x_16_R,AdvInterp2x_32_R} }; ScalerComplexBlock_t ScaleAdvInterp3x = { "AdvInterp3x", GFX_CAN_15|GFX_CAN_16|GFX_CAN_32|GFX_RGBONLY, 3,3, - 0,AdvInterp3x_15_L,AdvInterp3x_16_L,AdvInterp3x_32_L, - 0,AdvInterp3x_15_R,AdvInterp3x_16_R,AdvInterp3x_32_R +{ 0,AdvInterp3x_15_L,AdvInterp3x_16_L,AdvInterp3x_32_L}, +{ 0,AdvInterp3x_15_R,AdvInterp3x_16_R,AdvInterp3x_32_R} }; - +#endif diff --git a/src/gui/render_scalers.h b/src/gui/render_scalers.h index 9f1b163..ad5b5be 100644 --- a/src/gui/render_scalers.h +++ b/src/gui/render_scalers.h @@ -21,12 +21,20 @@ //#include "render.h" #include "video.h" +#if RENDER_USE_ADVANCED_SCALERS>0 +#define SCALER_MAXWIDTH 1280 +#define SCALER_MAXHEIGHT 1024 +#else +// reduced to save some memory +#define SCALER_MAXWIDTH 800 +#define SCALER_MAXHEIGHT 600 +#endif -#define SCALER_MAXWIDTH 1024 -#define SCALER_MAXHEIGHT 768 +#if RENDER_USE_ADVANCED_SCALERS>1 +#define SCALER_COMPLEXWIDTH 800 +#define SCALER_COMPLEXHEIGHT 600 +#endif -#define SCALER_COMPLEXWIDTH 512 -#define SCALER_COMPLEXHEIGHT 400 #define SCALER_BLOCKSIZE 16 typedef enum { @@ -35,16 +43,20 @@ typedef enum { typedef enum scalerOperation { scalerOpNormal, +#if RENDER_USE_ADVANCED_SCALERS>2 scalerOpAdvMame, scalerOpAdvInterp, scalerOpHQ, scalerOpSaI, scalerOpSuperSaI, scalerOpSuperEagle, +#endif +#if RENDER_USE_ADVANCED_SCALERS>0 scalerOpTV, scalerOpRGB, scalerOpScan, - scalerLast, +#endif + scalerLast } scalerOperation_t; typedef void (*ScalerLineHandler_t)(const void *src); @@ -54,6 +66,7 @@ extern Bit8u Scaler_Aspect[]; extern Bit8u diff_table[]; extern Bitu Scaler_ChangedLineIndex; extern Bit16u Scaler_ChangedLines[]; +#if RENDER_USE_ADVANCED_SCALERS>1 /* Not entirely happy about those +2's since they make a non power of 2, with muls instead of shift */ typedef Bit8u scalerChangeCache_t [SCALER_COMPLEXHEIGHT][SCALER_COMPLEXWIDTH / SCALER_BLOCKSIZE] ; typedef union { @@ -61,17 +74,20 @@ typedef union { Bit16u b16 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH]; Bit8u b8 [SCALER_COMPLEXHEIGHT] [SCALER_COMPLEXWIDTH]; } scalerFrameCache_t; +#endif typedef union { Bit32u b32 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; Bit16u b16 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; Bit8u b8 [SCALER_MAXHEIGHT] [SCALER_MAXWIDTH]; } scalerSourceCache_t; extern scalerSourceCache_t scalerSourceCache; +#if RENDER_USE_ADVANCED_SCALERS>1 extern scalerChangeCache_t scalerChangeCache; +#endif typedef ScalerLineHandler_t ScalerLineBlock_t[5][4]; typedef struct { - char *name; + const char *name; Bitu gfxFlags; Bitu xscale,yscale; ScalerComplexHandler_t Linear[4]; @@ -79,7 +95,7 @@ typedef struct { } ScalerComplexBlock_t; typedef struct { - char *name; + const char *name; Bitu gfxFlags; Bitu xscale,yscale; ScalerLineBlock_t Linear; @@ -97,13 +113,16 @@ extern ScalerSimpleBlock_t ScaleNormalDw; extern ScalerSimpleBlock_t ScaleNormalDh; extern ScalerSimpleBlock_t ScaleNormal2x; extern ScalerSimpleBlock_t ScaleNormal3x; +#if RENDER_USE_ADVANCED_SCALERS>0 extern ScalerSimpleBlock_t ScaleTV2x; extern ScalerSimpleBlock_t ScaleTV3x; extern ScalerSimpleBlock_t ScaleRGB2x; extern ScalerSimpleBlock_t ScaleRGB3x; extern ScalerSimpleBlock_t ScaleScan2x; extern ScalerSimpleBlock_t ScaleScan3x; +#endif /* Complex scalers */ +#if RENDER_USE_ADVANCED_SCALERS>2 extern ScalerComplexBlock_t ScaleHQ2x; extern ScalerComplexBlock_t ScaleHQ3x; extern ScalerComplexBlock_t Scale2xSaI; @@ -113,5 +132,8 @@ extern ScalerComplexBlock_t ScaleAdvMame2x; extern ScalerComplexBlock_t ScaleAdvMame3x; extern ScalerComplexBlock_t ScaleAdvInterp2x; extern ScalerComplexBlock_t ScaleAdvInterp3x; +#endif +#if RENDER_USE_ADVANCED_SCALERS>1 extern ScalerLineBlock_t ScalerCache; #endif +#endif diff --git a/src/gui/render_templates.h b/src/gui/render_templates.h index a3ce579..ba14a5f 100644 --- a/src/gui/render_templates.h +++ b/src/gui/render_templates.h @@ -152,6 +152,7 @@ #define D6 fc[+2 + 2*SCALER_COMPLEXWIDTH] +#if RENDER_USE_ADVANCED_SCALERS>1 static void conc3d(Cache,SBPP,DBPP) (const void * s) { #ifdef RENDER_NULL_INPUT if (!s) { @@ -208,6 +209,7 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) { render.scale.inLine++; render.scale.complexHandler(); } +#endif /* Simple scalers */ @@ -281,6 +283,8 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) { #if (DBPP > 8) +#if RENDER_USE_ADVANCED_SCALERS>0 + #define SCALERNAME TV2x #define SCALERWIDTH 2 #define SCALERHEIGHT 2 @@ -390,9 +394,14 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) { #undef SCALERHEIGHT #undef SCALERFUNC +#endif //#if RENDER_USE_ADVANCED_SCALERS>0 + #endif //#if (DBPP > 8) /* Complex scalers */ + +#if RENDER_USE_ADVANCED_SCALERS>2 + #if (SBPP == DBPP) @@ -549,6 +558,8 @@ static void conc3d(Cache,SBPP,DBPP) (const void * s) { #endif // (SBPP == DBPP) && !defined (CACHEWITHPAL) +#endif // #if RENDER_USE_ADVANCED_SCALERS>2 + #undef PSIZE #undef PTYPE #undef PMAKE diff --git a/src/gui/sdl_mapper.cpp b/src/gui/sdl_mapper.cpp index f3d87d0..96ba82b 100644 --- a/src/gui/sdl_mapper.cpp +++ b/src/gui/sdl_mapper.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdl_mapper.cpp,v 1.33 2007/02/22 15:12:48 c2woody Exp $ */ +/* $Id: sdl_mapper.cpp,v 1.39 2007/07/17 13:50:27 c2woody Exp $ */ #include #include @@ -42,6 +42,8 @@ enum { CLR_BLACK=0, CLR_WHITE=1, CLR_RED=2, + CLR_BLUE=3, + CLR_GREEN=4 }; enum BB_Types { @@ -64,6 +66,8 @@ enum BC_Types { #define MAXSTICKS 8 #define MAXACTIVE 16 +#define MAXBUTTON 32 +#define MAXBUTTON_CAP 16 class CEvent; class CHandlerEvent; @@ -600,23 +604,25 @@ public: if (_dummy) { sdl_joystick=NULL; axes=0; buttons=0; hats=0; - button_wrap=16; + button_wrap=0; + button_cap=0; axes_cap=0; hats_cap=0; return; } // initialize emulated joystick state emulated_axes=2; emulated_buttons=2; + emulated_hats=0; pos_axis_lists=new CBindList[4]; neg_axis_lists=new CBindList[4]; - button_lists=new CBindList[16]; + button_lists=new CBindList[MAXBUTTON]; hat_lists=new CBindList[4]; Bitu i; - for (i=0; i<16; i++) { + for (i=0; i16) button_wrap=16; - LOG_MSG("Using joystick %s with %d axes and %d buttons",SDL_JoystickName(stick),axes,buttons); + button_cap=buttons; + if (button_wrapping_enabled) { + button_wrap=emulated_buttons; + if (buttons>MAXBUTTON_CAP) button_cap = MAXBUTTON_CAP; + } + if (button_wrap > MAXBUTTON) button_wrap = MAXBUTTON; + axes_cap=emulated_axes; + if (axes_cap>axes) axes_cap=axes; + hats_cap=emulated_hats; + if (hats_cap>hats) hats_cap=hats; + LOG_MSG("Using joystick %s with %d axes, %d buttons and %d hat(s)",SDL_JoystickName(stick),axes,buttons,hats); } ~CStickBindGroup() { SDL_JoystickClose(sdl_joystick); @@ -723,9 +739,9 @@ public: /* query SDL joystick and activate bindings */ ActivateJoystickBoundEvents(); - bool button_pressed[16]; + bool button_pressed[MAXBUTTON]; Bitu i; - for (i=0; i<16; i++) button_pressed[i]=false; + for (i=0; i0) ActivateBindList(&pos_axis_lists[i],caxis_pos,false); - else if (caxis_pos<0) { + if (caxis_pos>1) { + if (old_neg_axis_state[i]) { + DeactivateBindList(&neg_axis_lists[i],false); + old_neg_axis_state[i] = false; + } + ActivateBindList(&pos_axis_lists[i],caxis_pos,false); + old_pos_axis_state[i] = true; + } else if (caxis_pos<-1) { + if (old_pos_axis_state[i]) { + DeactivateBindList(&pos_axis_lists[i],false); + old_pos_axis_state[i] = false; + } if (caxis_pos!=-32768) caxis_pos=(Sint16)abs(caxis_pos); else caxis_pos=32767; ActivateBindList(&neg_axis_lists[i],caxis_pos,false); + old_neg_axis_state[i] = true; + } else { + /* center */ + if (old_pos_axis_state[i]) { + DeactivateBindList(&pos_axis_lists[i],false); + old_pos_axis_state[i] = false; + } + if (old_neg_axis_state[i]) { + DeactivateBindList(&neg_axis_lists[i],false); + old_neg_axis_state[i] = false; + } } } - for (i=0; iaxes) axes_cap=axes; + hats_cap=emulated_hats; + if (hats_cap>hats) hats_cap=hats; + JOYSTICK_Enable(1,true); } @@ -885,9 +929,9 @@ public: /* query SDL joystick and activate bindings */ ActivateJoystickBoundEvents(); - bool button_pressed[16]; + bool button_pressed[MAXBUTTON]; Bitu i; - for (i=0; i<16; i++) button_pressed[i]=false; + for (i=0; iaxes) axes_cap=axes; + hats_cap=emulated_hats; + if (hats_cap>hats) hats_cap=hats; + JOYSTICK_Enable(1,true); JOYSTICK_Move_Y(1,1.0); } @@ -958,9 +1009,9 @@ public: /* query SDL joystick and activate bindings */ ActivateJoystickBoundEvents(); - bool button_pressed[16]; + bool button_pressed[MAXBUTTON]; Bitu i; - for (i=0; i<16; i++) button_pressed[i]=false; + for (i=0; iaxes) axes_cap=axes; + hats_cap=emulated_hats; + if (hats_cap>hats) hats_cap=hats; + JOYSTICK_Enable(1,true); button_state=0; } @@ -1137,8 +1195,8 @@ public: if (bt_state>hat_priority[i][3]) bt_state=hat_priority[i][3]; } - bool button_pressed[6]; - for (i=0; i<6; i++) button_pressed[i]=false; + bool button_pressed[MAXBUTTON]; + for (i=0; iSetColor(CLR_WHITE); + this->SetColor(CLR_GREEN); SetActiveEvent(event); + last_clicked=this; } protected: CEvent * event; @@ -1300,6 +1364,8 @@ void CCaptionButton::Change(const char * format,...) { mapper.redraw=true; } +static void change_action_text(const char* text,Bit8u col); + static void MAPPER_SaveBinds(void); class CBindButton : public CTextButton { public: @@ -1312,6 +1378,7 @@ public: case BB_Add: mapper.addbind=true; SetActiveBind(0); + change_action_text("Press a key/joystick button or move the joystick.",CLR_RED); break; case BB_Del: if (mapper.abindit!=mapper.aevent->bindlist.end()) { @@ -1546,6 +1613,13 @@ static struct { CCheckButton * mod1,* mod2,* mod3,* hold; } bind_but; + +static void change_action_text(const char* text,Bit8u col) { + bind_but.action->Change(text); + bind_but.action->SetColor(col); +} + + static void SetActiveBind(CBind * _bind) { mapper.abind=_bind; if (_bind) { @@ -1575,10 +1649,11 @@ static void SetActiveEvent(CEvent * event) { mapper.addbind=false; bind_but.event_title->Change("EVENT:%s",event ? event->GetName(): "none"); if (!event) { - bind_but.action->Change("Select an event to change"); + change_action_text("Select an event to change.",CLR_WHITE); bind_but.add->Enable(false); SetActiveBind(0); } else { + change_action_text("Select a different event or hit the Add/Del/Next buttons.",CLR_WHITE); mapper.abindit=event->bindlist.begin(); if (mapper.abindit!=event->bindlist.end()) { SetActiveBind(*(mapper.abindit)); @@ -1835,7 +1910,7 @@ static void CreateLayout(void) { new CTextButton(PX(6),00,124,20,"Keyboard Layout"); new CTextButton(PX(17),00,124,20,"Joystick Layout"); - bind_but.action=new CCaptionButton(200,330,0,0); + bind_but.action=new CCaptionButton(185,330,0,0); bind_but.event_title=new CCaptionButton(0,350,0,0); bind_but.bind_title=new CCaptionButton(00,365,0,0); @@ -1858,10 +1933,12 @@ static void CreateLayout(void) { bind_but.bind_title->Change("Bind Title"); } -static SDL_Color map_pal[4]={ +static SDL_Color map_pal[5]={ {0x00,0x00,0x00,0x00}, //0=black {0xff,0xff,0xff,0x00}, //1=white {0xff,0x00,0x00,0x00}, //2=red + {0x10,0x30,0xff,0x00}, //3=blue + {0x00,0xff,0x20,0x00} //4=green }; static void CreateStringBind(char * line) { @@ -2066,13 +2143,23 @@ void BIND_MappingEvents(void) { } } -static void CreateBindGroups(void) { - bindgroups.clear(); - new CKeyBindGroup(SDLK_LAST); +static void InitializeJoysticks(void) { mapper.sticks.num=0; mapper.sticks.num_groups=0; if (joytype != JOY_NONE) { mapper.sticks.num=SDL_NumJoysticks(); + if (joytype==JOY_AUTO) { + if (mapper.sticks.num>1) joytype=JOY_2AXIS; + else if (mapper.sticks.num) joytype=JOY_4AXIS; + else joytype=JOY_NONE; + } + } +} + +static void CreateBindGroups(void) { + bindgroups.clear(); + new CKeyBindGroup(SDLK_LAST); + if (joytype != JOY_NONE) { #if defined (REDUCE_JOYSTICK_POLLING) // direct access to the SDL joystick, thus removed from the event handling if (mapper.sticks.num) SDL_JoystickEventState(SDL_DISABLE); @@ -2082,31 +2169,29 @@ static void CreateBindGroups(void) { else return; #endif Bit8u joyno=0; - if (joytype==JOY_AUTO) { - if (mapper.sticks.num>1) joytype=JOY_2AXIS; - else if (mapper.sticks.num) joytype=JOY_4AXIS; - else joytype=JOY_NONE; - } switch (joytype) { case JOY_NONE: break; case JOY_4AXIS: mapper.sticks.stick[mapper.sticks.num_groups++]=new C4AxisBindGroup(joyno); - new CStickBindGroup(joyno+1U); + new CStickBindGroup(joyno+1U,true); break; case JOY_FCS: mapper.sticks.stick[mapper.sticks.num_groups++]=new CFCSBindGroup(joyno); - new CStickBindGroup(joyno+1U); + new CStickBindGroup(joyno+1U,true); break; case JOY_CH: mapper.sticks.stick[mapper.sticks.num_groups++]=new CCHBindGroup(joyno); - new CStickBindGroup(joyno+1U); + new CStickBindGroup(joyno+1U,true); break; case JOY_2AXIS: default: mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno); - if((joyno+1U) < mapper.sticks.num) + if((joyno+1U) < mapper.sticks.num) { mapper.sticks.stick[mapper.sticks.num_groups++]=new CStickBindGroup(joyno+1U); + } else { + new CStickBindGroup(joyno+1U,true); + } break; } } @@ -2146,7 +2231,8 @@ void MAPPER_Run(bool pressed) { if (mapper.surface == NULL) E_Exit("Could not initialize video mode for mapper: %s",SDL_GetError()); /* Set some palette entries */ - SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 4); + SDL_SetPalette(mapper.surface, SDL_LOGPAL|SDL_PHYSPAL, map_pal, 0, 5); + last_clicked=NULL; /* Go in the event loop */ mapper.exit=false; mapper.redraw=true; @@ -2170,6 +2256,7 @@ void MAPPER_Run(bool pressed) { } void MAPPER_Init(void) { + InitializeJoysticks(); CreateLayout(); CreateBindGroups(); if (!MAPPER_LoadBinds()) CreateDefaultBinds(); diff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp index 680ed73..379cc9d 100644 --- a/src/gui/sdlmain.cpp +++ b/src/gui/sdlmain.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sdlmain.cpp,v 1.127 2007/01/24 16:29:09 harekiet Exp $ */ +/* $Id: sdlmain.cpp,v 1.131 2007/06/12 20:22:08 c2woody Exp $ */ #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -28,6 +28,9 @@ #include #include #include +#ifdef WIN32 +#include +#endif #include "SDL.h" @@ -278,6 +281,7 @@ check_surface: else if (flags & GFX_LOVE_15) testbpp=15; else if (flags & GFX_LOVE_16) testbpp=16; else if (flags & GFX_LOVE_32) testbpp=32; + else testbpp=0; check_gotbpp: if (sdl.desktop.fullscreen) gotbpp=SDL_VideoModeOK(640,480,testbpp,SDL_FULLSCREEN|SDL_HWSURFACE|SDL_HWPALETTE); else gotbpp=sdl.desktop.bpp; @@ -395,7 +399,7 @@ Bitu GFX_SetSize(Bitu width,Bitu height,Bitu flags,double scalex,double scaley,G sdl.draw.scalex=scalex; sdl.draw.scaley=scaley; - Bitu bpp; + Bitu bpp=0; Bitu retFlags = 0; if (sdl.blit.surface) { @@ -433,11 +437,17 @@ dosurface: sdl.surface=SDL_SetVideoMode(width,height,bpp,(flags & GFX_CAN_RANDOM) ? SDL_SWSURFACE : SDL_HWSURFACE); #ifdef WIN32 if (sdl.surface == NULL) { - LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled."); SDL_QuitSubSystem(SDL_INIT_VIDEO); - putenv("SDL_VIDEODRIVER=windib"); + if (!sdl.using_windib) { + LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with windib enabled."); + putenv("SDL_VIDEODRIVER=windib"); + sdl.using_windib=true; + } else { + LOG_MSG("Failed to create hardware surface.\nRestarting video subsystem with directx enabled."); + putenv("SDL_VIDEODRIVER=directx"); + sdl.using_windib=false; + } SDL_InitSubSystem(SDL_INIT_VIDEO); - sdl.using_windib=true; sdl.surface = SDL_SetVideoMode(width,height,bpp,SDL_HWSURFACE); } #endif @@ -490,6 +500,10 @@ dosurface: sdl.surface->format->Bmask, 0); if (!sdl.blit.surface || (!sdl.blit.surface->flags&SDL_HWSURFACE)) { + if (sdl.blit.surface) { + SDL_FreeSurface(sdl.blit.surface); + sdl.blit.surface=0; + } LOG_MSG("Failed to create ddraw surface, back to normal surface."); goto dosurface; } @@ -1133,7 +1147,11 @@ void Mouse_AutoLock(bool enable) { static void HandleMouseMotion(SDL_MouseMotionEvent * motion) { if (sdl.mouse.locked || !sdl.mouse.autoenable) - Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100,(float)motion->yrel*sdl.mouse.sensitivity/100,(float)(motion->x-sdl.clip.x)/(sdl.clip.w-1)*sdl.mouse.sensitivity/100,(float)(motion->y-sdl.clip.y)/(sdl.clip.h-1)*sdl.mouse.sensitivity/100.0,sdl.mouse.locked); + Mouse_CursorMoved((float)motion->xrel*sdl.mouse.sensitivity/100.0f, + (float)motion->yrel*sdl.mouse.sensitivity/100.0f, + (float)(motion->x-sdl.clip.x)/(sdl.clip.w-1)*sdl.mouse.sensitivity/100.0f, + (float)(motion->y-sdl.clip.y)/(sdl.clip.h-1)*sdl.mouse.sensitivity/100.0f, + sdl.mouse.locked); } static void HandleMouseButton(SDL_MouseButtonEvent * button) { @@ -1183,7 +1201,7 @@ void GFX_Events() { SDL_Event event; #if defined (REDUCE_JOYSTICK_POLLING) static int poll_delay=0; - int time=SDL_GetTicks(); + int time=GetTicks(); if (time-poll_delay>20) { poll_delay=time; if (sdl.num_joysticks>0) SDL_JoystickUpdate(); @@ -1293,6 +1311,23 @@ void GFX_Events() { } } +#if defined (WIN32) +static BOOL WINAPI ConsoleEventHandler(DWORD event) { + switch (event) { + case CTRL_SHUTDOWN_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_CLOSE_EVENT: + case CTRL_BREAK_EVENT: + raise(SIGTERM); + return TRUE; + case CTRL_C_EVENT: + default: //pass to the next handler + return FALSE; + } +} +#endif + + /* static variable to show wether there is not a valid stdout. * Fixes some bugs when -noconsole is used in a read only directory */ static bool no_stdout = false; @@ -1345,6 +1380,10 @@ int main(int argc, char* argv[]) { DEBUG_SetupConsole(); #endif +#if defined(WIN32) + SetConsoleCtrlHandler((PHANDLER_ROUTINE) ConsoleEventHandler,TRUE); +#endif + #ifdef OS2 PPIB pib; PTIB tib; @@ -1373,12 +1412,16 @@ int main(int argc, char* argv[]) { char sdl_drv_name[128]; if (getenv("SDL_VIDEODRIVER")==NULL) { if (SDL_VideoDriverName(sdl_drv_name,128)!=NULL) { + sdl.using_windib=false; if (strcmp(sdl_drv_name,"directx")!=0) { SDL_QuitSubSystem(SDL_INIT_VIDEO); putenv("SDL_VIDEODRIVER=directx"); - SDL_InitSubSystem(SDL_INIT_VIDEO); + if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) { + putenv("SDL_VIDEODRIVER=windib"); + if (SDL_InitSubSystem(SDL_INIT_VIDEO)<0) E_Exit("Can't init SDL Video %s",SDL_GetError()); + sdl.using_windib=true; + } } - sdl.using_windib=false; } } else { char* sdl_videodrv = getenv("SDL_VIDEODRIVER"); diff --git a/src/hardware/fmopl.c b/src/hardware/fmopl.c index 9427447..9e1500a 100644 --- a/src/hardware/fmopl.c +++ b/src/hardware/fmopl.c @@ -329,51 +329,51 @@ static const int slot_array[32]= /* key scale level */ /* table is 3dB/octave , DV converts this into 6dB/octave */ /* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ -#define DV (0.1875/2.0) +#define SC(x) ((UINT32)((x)/(0.1875/2.0))) static const UINT32 ksl_tab[8*16]= { /* OCT 0 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), /* OCT 1 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, - 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.750), SC(1.125), SC(1.500), + SC(1.875), SC(2.250), SC(2.625), SC(3.000), /* OCT 2 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, - 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, - 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(1.125), SC(1.875), SC(2.625), + SC(3.000), SC(3.750), SC(4.125), SC(4.500), + SC(4.875), SC(5.250), SC(5.625), SC(6.000), /* OCT 3 */ - 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, - 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, - 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, - 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(1.875), + SC(3.000), SC(4.125), SC(4.875), SC(5.625), + SC(6.000), SC(6.750), SC(7.125), SC(7.500), + SC(7.875), SC(8.250), SC(8.625), SC(9.000), /* OCT 4 */ - 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, - 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, - 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, - 10.875/DV,11.250/DV,11.625/DV,12.000/DV, + SC(0.000), SC(0.000), SC(3.000), SC(4.875), + SC(6.000), SC(7.125), SC(7.875), SC(8.625), + SC(9.000), SC(9.750),SC(10.125),SC(10.500), + SC(10.875),SC(11.250),SC(11.625),SC(12.000), /* OCT 5 */ - 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, - 9.000/DV,10.125/DV,10.875/DV,11.625/DV, - 12.000/DV,12.750/DV,13.125/DV,13.500/DV, - 13.875/DV,14.250/DV,14.625/DV,15.000/DV, + SC(0.000), SC(3.000), SC(6.000), SC(7.875), + SC(9.000),SC(10.125),SC(10.875),SC(11.625), + SC(12.000),SC(12.750),SC(13.125),SC(13.500), + SC(13.875),SC(14.250),SC(14.625),SC(15.000), /* OCT 6 */ - 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, - 12.000/DV,13.125/DV,13.875/DV,14.625/DV, - 15.000/DV,15.750/DV,16.125/DV,16.500/DV, - 16.875/DV,17.250/DV,17.625/DV,18.000/DV, + SC(0.000), SC(6.000), SC(9.000),SC(10.875), + SC(12.000),SC(13.125),SC(13.875),SC(14.625), + SC(15.000),SC(15.750),SC(16.125),SC(16.500), + SC(16.875),SC(17.250),SC(17.625),SC(18.000), /* OCT 7 */ - 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, - 15.000/DV,16.125/DV,16.875/DV,17.625/DV, - 18.000/DV,18.750/DV,19.125/DV,19.500/DV, - 19.875/DV,20.250/DV,20.625/DV,21.000/DV + SC(0.000), SC(9.000),SC(12.000),SC(13.875), + SC(15.000),SC(16.125),SC(16.875),SC(17.625), + SC(18.000),SC(18.750),SC(19.125),SC(19.500), + SC(19.875),SC(20.250),SC(20.625),SC(21.000) }; -#undef DV +#undef SC /* sustain level table (3dB per step) */ /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ @@ -493,13 +493,13 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), /* multiple table */ -#define ML 2 +#define SC(x) ((UINT32)((x)*2)) static const UINT8 mul_tab[16]= { /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, - 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML + SC(0.50), SC(1.00), SC(2.00), SC(3.00), SC(4.00), SC(5.00), SC(6.00), SC(7.00), + SC(8.00), SC(9.00),SC(10.00),SC(10.00),SC(12.00),SC(12.00),SC(15.00),SC(15.00) }; -#undef ML +#undef SC /* TL_TAB_LEN is calculated as: * 12 - sinus amplitude bits (Y axis) @@ -1301,17 +1301,17 @@ static void OPL_initalize(FM_OPL *OPL) /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ /* One entry from LFO_AM_TABLE lasts for 64 samples */ - OPL->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase; + OPL->lfo_am_inc = (UINT32)((1.0 / 64.0 ) * (1<freqbase); /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ - OPL->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase; + OPL->lfo_pm_inc = (UINT32)((1.0 / 1024.0) * (1<freqbase); /*logerror ("OPL->lfo_am_inc = %8x ; OPL->lfo_pm_inc = %8x\n", OPL->lfo_am_inc, OPL->lfo_pm_inc);*/ /* Noise generator: a step takes 1 sample */ - OPL->noise_f = (1.0 / 1.0) * (1<freqbase; + OPL->noise_f = (UINT32)((1.0 / 1.0) * (1<freqbase); - OPL->eg_timer_add = (1<freqbase; + OPL->eg_timer_add = (UINT32)((1<freqbase); OPL->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, OPL->eg_timer_overflow);*/ diff --git a/src/hardware/gus.cpp b/src/hardware/gus.cpp index 0b53a85..33cd96f 100644 --- a/src/hardware/gus.cpp +++ b/src/hardware/gus.cpp @@ -45,7 +45,7 @@ using namespace std; #define GUS_BASE myGUS.portbase #define GUS_RATE myGUS.rate -#define LOG_GUS +#define LOG_GUS 0 Bit8u adlib_commandreg; static MixerChannel * gus_chan; @@ -58,7 +58,6 @@ static Bit16u vol16bit[4096]; #endif static Bit32u pantable[16]; -static Bitu show_test=0; class GUSChannels; static void CheckVoiceIrq(void); @@ -239,26 +238,6 @@ public: double realadd = (frameadd*(double)myGUS.basefreq/(double)GUS_RATE) * (double)(1 << RAMP_FRACT); RampAdd = (Bit32u)realadd; } - void ShowWave(void) { - LOG_GUS("Wave %2d Ctrl %02x Current %d Start %d End %d Add %3.3f ", - channum, - ReadWaveCtrl(), - WaveAddr>>WAVE_FRACT, - WaveStart>>WAVE_FRACT, - WaveEnd>>WAVE_FRACT, - (float)WaveAdd/(float)(1 << WAVE_FRACT) - ); - } - void ShowRamp(void) { - LOG_GUS("Ramp %2d Ctrl %02X Current %d Start %d End %d Add %d", - channum, - ReadRampCtrl(), - RampVol >> RAMP_FRACT, - RampStart >> RAMP_FRACT, - RampEnd >> RAMP_FRACT, - RampAdd >> RAMP_FRACT - ); - } INLINE void WaveUpdate(void) { if (WaveCtrl & 0x3) return; Bit32s WaveLeft; @@ -334,12 +313,7 @@ public: bool eightbit; if (RampCtrl & WaveCtrl & 3) return; eightbit = ((WaveCtrl & 0x4) == 0); -#if 0 - if (!(show_test & 1023)) { - ShowWave(); - ShowRamp(); - } -#endif + for(i=0;i<(int)len;i++) { // Get sample tmpsamp = GetSample(WaveAdd, WaveAddr, eightbit); @@ -463,7 +437,9 @@ static Bit16u ExecuteReadRegister(void) { CheckVoiceIrq(); return (Bit16u)(tmpreg << 8); default: - LOG_GUS("Read Register num 0x%x", myGUS.gRegSelect); +#if LOG_GUS + LOG_MSG("Read Register num 0x%x", myGUS.gRegSelect); +#endif return myGUS.gRegData; } } @@ -564,7 +540,9 @@ static void ExecuteGlobRegister(void) { myGUS.ActiveMask=0xffffffffU >> (32-myGUS.ActiveChannels); gus_chan->Enable(true); myGUS.basefreq = (Bit32u)((float)1000000/(1.619695497*(float)(myGUS.ActiveChannels))); - LOG_GUS("GUS set to %d channels", myGUS.ActiveChannels); +#if LOG_GUS + LOG_MSG("GUS set to %d channels", myGUS.ActiveChannels); +#endif for (i=0;iUpdateWaveRamp(); break; case 0x10: // Undocumented register used in Fast Tracker 2 @@ -607,7 +585,10 @@ static void ExecuteGlobRegister(void) { GUSReset(); break; default: - LOG_GUS("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData); +#if LOG_GUS + LOG_MSG("Unimplemented global register %x -- %x", myGUS.gRegSelect, myGUS.gRegData); +#endif + break; } return; } @@ -645,7 +626,9 @@ static Bitu read_gus(Bitu port,Bitu iolen) { return 0; } default: - LOG_GUS("Read GUS at port 0x%x", port); +#if LOG_GUS + LOG_MSG("Read GUS at port 0x%x", port); +#endif break; } @@ -692,11 +675,15 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) { if (myGUS.mixControl & 0x40) { // IRQ configuration, only use low bits for irq 1 if (irqtable[val & 0x7]) myGUS.irq1=irqtable[val & 0x7]; - LOG_GUS("Assigned GUS to IRQ %d", myGUS.irq1); +#if LOG_GUS + LOG_MSG("Assigned GUS to IRQ %d", myGUS.irq1); +#endif } else { // DMA configuration, only use low bits for dma 1 if (dmatable[val & 0x7]) myGUS.dma1=dmatable[val & 0x7]; - LOG_GUS("Assigned GUS to DMA %d", myGUS.dma1); +#if LOG_GUS + LOG_MSG("Assigned GUS to DMA %d", myGUS.dma1); +#endif } break; case 0x302: @@ -721,7 +708,9 @@ static void write_gus(Bitu port,Bitu val,Bitu iolen) { if(myGUS.gDramAddr < sizeof(GUSRam)) GUSRam[myGUS.gDramAddr] = val; break; default: - LOG_GUS("Write GUS at port 0x%x with %x", port, val); +#if LOG_GUS + LOG_MSG("Write GUS at port 0x%x with %x", port, val); +#endif break; } } diff --git a/src/hardware/iohandler.cpp b/src/hardware/iohandler.cpp index c170d8c..48275f0 100644 --- a/src/hardware/iohandler.cpp +++ b/src/hardware/iohandler.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: iohandler.cpp,v 1.26 2007/02/22 08:32:21 qbix79 Exp $ */ +/* $Id: iohandler.cpp,v 1.28 2007/06/12 20:22:08 c2woody Exp $ */ #include #include "dosbox.h" @@ -174,7 +174,7 @@ static Bits IOFaultCore(void) { inline void IO_USEC_read_delay_old() { if(CPU_CycleMax > static_cast((IODELAY_READ_MICROS*1000.0))) { // this could be calculated whenever CPU_CycleMax changes - Bitu delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_READ_MICROS); + Bits delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_READ_MICROS); if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc; else CPU_Cycles = 0; } @@ -183,7 +183,7 @@ inline void IO_USEC_read_delay_old() { inline void IO_USEC_write_delay_old() { if(CPU_CycleMax > static_cast((IODELAY_WRITE_MICROS*1000.0))) { // this could be calculated whenever CPU_CycleMax changes - Bitu delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_WRITE_MICROS); + Bits delaycyc = static_cast((CPU_CycleMax/1000)*IODELAY_WRITE_MICROS); if(CPU_Cycles > delaycyc) CPU_Cycles -= delaycyc; else CPU_Cycles = 0; } @@ -194,14 +194,14 @@ inline void IO_USEC_write_delay_old() { #define IODELAY_WRITE_MICROSk (Bit32u)(1024/0.75) inline void IO_USEC_read_delay() { - Bitu delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk; + Bits delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk; if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; //Else port acces will set cycles to 0. which might trigger problem with games which read 16 bit values CPU_Cycles -= delaycyc; CPU_IODelayRemoved += delaycyc; } inline void IO_USEC_write_delay() { - Bitu delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk; + Bits delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk; if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc=0; CPU_Cycles -= delaycyc; CPU_IODelayRemoved += delaycyc; @@ -227,7 +227,6 @@ void IO_WriteB(Bitu port,Bitu val) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x08; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); @@ -263,7 +262,6 @@ void IO_WriteW(Bitu port,Bitu val) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x0a; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); @@ -299,7 +297,6 @@ void IO_WriteD(Bitu port,Bitu val) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x0c; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); @@ -330,7 +327,6 @@ Bitu IO_ReadB(Bitu port) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x00; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); @@ -366,7 +362,6 @@ Bitu IO_ReadW(Bitu port) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x02; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); @@ -402,7 +397,6 @@ Bitu IO_ReadD(Bitu port) { RealPt icb = CALLBACK_RealPointer(call_priv_io); SegSet16(cs,RealSeg(icb)); reg_eip = RealOff(icb)+0x04; - FillFlags(); CPU_Exception(cpu.exception.which,cpu.exception.error); DOSBOX_RunMachine(); diff --git a/src/hardware/keyboard.cpp b/src/hardware/keyboard.cpp index 5bd1dbb..3732380 100644 --- a/src/hardware/keyboard.cpp +++ b/src/hardware/keyboard.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: keyboard.cpp,v 1.37 2007/01/21 11:01:54 qbix79 Exp $ */ +/* $Id: keyboard.cpp,v 1.39 2007/06/12 20:22:08 c2woody Exp $ */ #include "dosbox.h" #include "keyboard.h" @@ -66,7 +66,6 @@ static void KEYBOARD_TransferBuffer(Bitu val) { LOG(LOG_KEYBOARD,LOG_NORMAL)("Transfer started with empty buffer"); return; } - Bit8u data=keyb.buffer[keyb.pos]; KEYBOARD_SetPort60(keyb.buffer[keyb.pos]); if (++keyb.pos>=KEYBUFSIZE) keyb.pos-=KEYBUFSIZE; keyb.used--; @@ -179,9 +178,13 @@ static Bitu read_p61(Bitu port,Bitu iolen) { return port_61_data; } +extern void TIMER_SetGate2(bool); static void write_p61(Bitu port,Bitu val,Bitu iolen) { - if ((port_61_data ^ val) & 3) PCSPEAKER_SetType(val & 3); - port_61_data=val; + if ((port_61_data ^ val) & 3) { + if((port_61_data ^ val) & 1) TIMER_SetGate2(val&0x1); + PCSPEAKER_SetType(val & 3); + } + port_61_data = val; } static void write_p64(Bitu port,Bitu val,Bitu iolen) { diff --git a/src/hardware/memory.cpp b/src/hardware/memory.cpp index 4dee16b..5991580 100644 --- a/src/hardware/memory.cpp +++ b/src/hardware/memory.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: memory.cpp,v 1.48 2007/01/14 18:44:01 c2woody Exp $ */ +/* $Id: memory.cpp,v 1.51 2007/07/19 18:58:39 c2woody Exp $ */ #include "dosbox.h" #include "mem.h" @@ -63,11 +63,27 @@ public: flags=PFLAG_INIT|PFLAG_NOCODE; } Bitu readb(PhysPt addr) { +#if C_DEBUG LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); +#else + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("Illegal read from %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); + } +#endif return 0; } void writeb(PhysPt addr,Bitu val) { +#if C_DEBUG LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); +#else + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("Illegal write to %x, CS:IP %8x:%8x",addr,SegValue(cs),reg_eip); + } +#endif } }; @@ -143,12 +159,12 @@ Bitu mem_strlen(PhysPt pt) { if (!mem_readb_inline(pt+x)) return x; x++; } - return 0; //Hope this doesn't happend + return 0; //Hope this doesn't happen } void mem_strcpy(PhysPt dest,PhysPt src) { Bit8u r; - while (r=mem_readb(src++)) mem_writeb_inline(dest++,r); + while ( (r = mem_readb(src++)) ) mem_writeb_inline(dest++,r); mem_writeb_inline(dest,0); } @@ -157,14 +173,14 @@ void mem_memcpy(PhysPt dest,PhysPt src,Bitu size) { } void MEM_BlockRead(PhysPt pt,void * data,Bitu size) { - Bit8u * write=(Bit8u *) data; + Bit8u * write=reinterpret_cast(data); while (size--) { *write++=mem_readb_inline(pt++); } } -void MEM_BlockWrite(PhysPt pt,void * data,Bitu size) { - Bit8u * read=(Bit8u *) data; +void MEM_BlockWrite(PhysPt pt,void const * const data,Bitu size) { + Bit8u const * read = reinterpret_cast(data); while (size--) { mem_writeb_inline(pt++,*read++); } diff --git a/src/hardware/mixer.cpp b/src/hardware/mixer.cpp index 926e043..fa6247e 100644 --- a/src/hardware/mixer.cpp +++ b/src/hardware/mixer.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: mixer.cpp,v 1.44 2007/01/08 19:45:40 qbix79 Exp $ */ +/* $Id: mixer.cpp,v 1.46 2007/06/12 20:22:08 c2woody Exp $ */ /* Remove the sdl code from here and have it handeld in the sdlmain. @@ -429,7 +429,7 @@ static void MIXER_CallBack(void * userdata, Uint8 *stream, int len) { } /* Reduce done count in all channels */ for (MixerChannel * chan=mixer.channels;chan;chan=chan->next) { - if (chan->done>need) chan->done-=reduce; + if (chan->done>reduce) chan->done-=reduce; else chan->done=0; } @@ -595,7 +595,7 @@ void MIXER_Init(Section* sec) { spec.channels=2; spec.callback=MIXER_CallBack; spec.userdata=NULL; - spec.samples=mixer.blocksize; + spec.samples=(Uint16)mixer.blocksize; mixer.tick_remain=0; if (mixer.nosound) { diff --git a/src/hardware/pcspeaker.cpp b/src/hardware/pcspeaker.cpp index 6aa2811..dd328a6 100644 --- a/src/hardware/pcspeaker.cpp +++ b/src/hardware/pcspeaker.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - /* $Id: pcspeaker.cpp,v 1.23 2007/01/08 19:45:40 qbix79 Exp $ */ + /* $Id: pcspeaker.cpp,v 1.24 2007/07/15 16:36:27 c2woody Exp $ */ #include #include "dosbox.h" @@ -57,6 +57,7 @@ static struct { float volwant,volcur; Bitu last_ticks; float last_index; + Bitu min_tr; DelayEntry entries[SPKR_ENTRIES]; Bitu used; } spkr; @@ -134,6 +135,9 @@ static void ForwardPIT(float newindex) { spkr.pit_last=-SPKR_VOLUME; if (spkr.mode==SPKR_PIT_ON) AddDelayEntry(delay_base,spkr.pit_last); spkr.pit_index=spkr.pit_half; + /* Load the new count */ + spkr.pit_half=spkr.pit_new_half; + spkr.pit_max=spkr.pit_new_max; } else { spkr.pit_index+=passed; return; @@ -189,8 +193,8 @@ void PCSPEAKER_SetCounter(Bitu cntr,Bitu mode) { spkr.pit_max=(1000.0f/PIT_TICK_RATE)*cntr; break; case 3: /* Square wave generator */ - if (cntr<=40) { - /* Makes DIGGER sound better */ + if (cntr @@ -83,7 +83,7 @@ static void write_command(Bitu port,Bitu val,Bitu iolen) { if (val&0x04) E_Exit("PIC: 4 byte interval not handled"); if (val&0x08) E_Exit("PIC: level triggered mode not handled"); if (val&0xe0) E_Exit("PIC: 8080/8085 mode not handled"); - pic->single=val&0x02; + pic->single=(val&0x02)==0x02; pic->icw_index=1; // next is ICW2 pic->icw_words=2 + (val&0x01); // =3 if ICW4 needed } else if (GCC_UNLIKELY(val&0x08)) { // OCW3 issued @@ -118,7 +118,7 @@ static void write_command(Bitu port,Bitu val,Bitu iolen) { } } } - if (val&0x80); // perform rotation +// if (val&0x80); // perform rotation } else { // nonspecific EOI if (PIC_IRQActive<(irq_base+8)) { irqs[PIC_IRQActive].inservice=false; @@ -130,7 +130,7 @@ static void write_command(Bitu port,Bitu val,Bitu iolen) { } } } - if (val&0x80); // perform rotation +// if (val&0x80); // perform rotation } } else { if ((val&0x40)==0) { // rotate in auto EOI mode @@ -203,7 +203,7 @@ static void write_data(Bitu port,Bitu val,Bitu iolen) { LOG(LOG_PIC,LOG_NORMAL)("%d:ICW 4 %X",port==0x21 ? 0 : 1,val); if ((val&0x01)==0) E_Exit("PIC:ICW4: %x, 8085 mode not handled",val); - if ((val&0x10)!=0) E_Exit("PIC:ICW4: %x, special fully-nested mode not handled",val); + if ((val&0x10)!=0) LOG_MSG("PIC:ICW4: %x, special fully-nested mode not handled",val); if(pic->icw_index++ >= pic->icw_words) pic->icw_index=0; break; @@ -232,7 +232,6 @@ static Bitu read_command(Bitu port,Bitu iolen) { } static Bitu read_data(Bitu port,Bitu iolen) { - PIC_Controller * pic=&pics[port==0x21 ? 0 : 1]; Bitu irq_base=(port==0x21) ? 0 : 8; Bitu i;Bit8u ret=0;Bit8u b=1; for (i=irq_base;i<=irq_base+7;i++) { @@ -387,7 +386,7 @@ void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val) { return; } PICEntry * entry=pic.free_entry; - entry->index=delay+PIC_TickIndex();; + entry->index=delay+PIC_TickIndex(); entry->event=handler; entry->value=val; pic.free_entry=pic.free_entry->next; diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 92f7b8b..6f73b51 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: sblaster.cpp,v 1.63 2007/02/24 21:07:22 c2woody Exp $ */ +/* $Id: sblaster.cpp,v 1.65 2007/06/14 18:06:59 qbix79 Exp $ */ #include #include @@ -158,7 +158,7 @@ struct SB_INFO { static SB_INFO sb; -static char * copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; +static char const * const copyright_string="COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; static Bit8u DSP_cmd_len[256] = { // 0,0,0,0, 1,2,0,0, 0,0,0,0, 0,0,2,1, // 0x00 for SB16. but breaks sbpro @@ -355,9 +355,11 @@ INLINE Bit8u decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits& scale) { static void GenerateDMASound(Bitu size) { Bitu read=0;Bitu done=0;Bitu i=0; - if (sb.dma.left<=sb.dma.min) { - size=sb.dma.left; - } + + if(sb.dma.autoinit) { + if (sb.dma.left <= size) size = sb.dma.left; + } else if (sb.dma.left <= sb.dma.min) size = sb.dma.left; + switch (sb.dma.mode) { case DSP_DMA_2: read=sb.dma.chan->Read(size,sb.dma.buf.b8); @@ -534,7 +536,7 @@ static void DSP_RaiseIRQEvent(Bitu val) { } static void DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool stereo) { - char * type; + char const * type; sb.mode=MODE_DMA_MASKED; sb.chan->FillUp(); sb.dma.left=sb.dma.total; @@ -847,7 +849,7 @@ static void DSP_DoCommand(void) { case 0xe3: /* DSP Copyright */ { DSP_FlushData(); - for (Bit32u i=0;i<=strlen(copyright_string);i++) { + for (size_t i=0;i<=strlen(copyright_string);i++) { DSP_AddData(copyright_string[i]); } } diff --git a/src/hardware/serialport/directserial_win32.h b/src/hardware/serialport/directserial_win32.h index 9f1eaac..1491c72 100644 --- a/src/hardware/serialport/directserial_win32.h +++ b/src/hardware/serialport/directserial_win32.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: directserial_win32.h,v 1.4 2007/01/13 08:35:49 qbix79 Exp $ */ +/* $Id: directserial_win32.h,v 1.5 2007/05/23 08:05:22 qbix79 Exp $ */ // include guard #ifndef DOSBOX_DIRECTSERIAL_WIN32_H @@ -31,6 +31,7 @@ #define DIRECTSERIAL_AVAILIBLE #include "serialport.h" +#include //To prevent compilation problems with windows.h including winsock.h #include class CDirectSerial : public CSerial { diff --git a/src/hardware/serialport/misc_util.cpp b/src/hardware/serialport/misc_util.cpp index 5b99971..9968cd9 100644 --- a/src/hardware/serialport/misc_util.cpp +++ b/src/hardware/serialport/misc_util.cpp @@ -5,39 +5,13 @@ /*****************************************************************************/ // C++ SDLnet wrapper -// Socket inheritance -#if defined LINUX || defined OS2 -#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET) -#ifdef OS2 -typedef int socklen_t; -#endif -#include -#include -#include -#define SOCKET int - -#elif defined WIN32 -#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET) -#include -typedef int socklen_t; - -#elif defined __APPLE__ -#define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET) -#include -#include -#include -#define SOCKET socklen_t - -#else -#define CAPWORD NETWRAPPER_TCP -#endif - #include "misc_util.h" - struct _TCPsocketX { int ready; +#ifdef NATIVESOCKETS SOCKET channel; +#endif IPaddress remoteAddress; IPaddress localAddress; int sflag; @@ -67,7 +41,7 @@ TCPClientSocket::TCPClientSocket(int platformsocket) { // fill the SDL socket manually ((struct _TCPsocketX*)nativetcpstruct)->ready=0; ((struct _TCPsocketX*)nativetcpstruct)->sflag=0; - ((struct _TCPsocketX*)nativetcpstruct)->channel=platformsocket; + ((struct _TCPsocketX*)nativetcpstruct)->channel=(SOCKET) platformsocket; sockaddr_in sa; socklen_t sz; sz=sizeof(sa); @@ -146,7 +120,8 @@ TCPClientSocket::TCPClientSocket(const char* destination, Bit16u port) { listensocketset=0; IPaddress openip; - if (!SDLNet_ResolveHost(&openip,destination,port)) { + //Ancient versions of SDL_net had this as char*. People still appear to be using this one. + if (!SDLNet_ResolveHost(&openip,const_cast(destination),port)) { listensocketset = SDLNet_AllocSocketSet(1); if(!listensocketset) return; mysock = SDLNet_TCP_Open(&openip); @@ -258,7 +233,7 @@ bool TCPClientSocket::SendArrayBuffered(Bit8u* data, Bitu bufsize) { while( // first case, buffer already full - /*if(sendbufferindex==(sendbuffersize-1)) { + if(sendbufferindex==(sendbuffersize-1)) { // buffer is full, get rid of it sendbuffer[sendbufferindex]=data; sendbufferindex=0; @@ -267,9 +242,9 @@ bool TCPClientSocket::SendArrayBuffered(Bit8u* data, Bitu bufsize) { isopen=false; return false; } - }*/ -//} - + } +} +*/ void TCPClientSocket::FlushBuffer() { if(sendbufferindex) { if(SDLNet_TCP_Send(mysock, sendbuffer, diff --git a/src/hardware/serialport/misc_util.h b/src/hardware/serialport/misc_util.h index 9b89ac1..08a3612 100644 --- a/src/hardware/serialport/misc_util.h +++ b/src/hardware/serialport/misc_util.h @@ -1,24 +1,48 @@ #ifndef SDLNETWRAPPER_H #define SDLNETWRAPPER_H +#ifndef DOSBOX_DOSBOX_H +#include "dosbox.h" +#endif + #if C_MODEM -#include "SDL_net.h" +# ifndef DOSBOX_SUPPORT_H #include "support.h" - -#if defined LINUX || defined OS2 -#define NATIVESOCKETS - -#elif defined WIN32 -#define NATIVESOCKETS - -#else #endif // Netwrapper Capabilities #define NETWRAPPER_TCP 1 #define NETWRAPPER_TCP_NATIVESOCKET 2 +#if defined WIN32 + #define NATIVESOCKETS + #include + #include //for socklen_t + //typedef int socklen_t; + +//Tests for BSD/OS2/LINUX +#elif defined HAVE_STDLIB_H && defined HAVE_SYS_TYPES_H && defined HAVE_SYS_SOCKET_H && defined HAVE_NETINET_IN_H + #define NATIVESOCKETS + #define SOCKET int + #include //darwin + #include //darwin + #include + #include + #include + //socklen_t should be handled by configure +#endif + +#ifdef NATIVESOCKETS + #define CAPWORD (NETWRAPPER_TCP|NETWRAPPER_TCP_NATIVESOCKET) +#else + #define CAPWORD NETWRAPPER_TCP +#endif + +#include "SDL_net.h" + + + Bit32u Netwrapper_GetCapabilities(); @@ -74,6 +98,6 @@ class TCPServerSocket { }; -#endif +#endif //C_MODEM -#endif //#if C_MODEM +#endif //# SDLNETWRAPPER_H diff --git a/src/hardware/serialport/nullmodem.cpp b/src/hardware/serialport/nullmodem.cpp index c0ca3f3..f0853c1 100644 --- a/src/hardware/serialport/nullmodem.cpp +++ b/src/hardware/serialport/nullmodem.cpp @@ -90,6 +90,7 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) { } // socket inheritance if(getBituSubstring("inhsocket:", &bool_temp, cmd)) { +#ifdef NATIVESOCKETS if(Netwrapper_GetCapabilities()&NETWRAPPER_TCP_NATIVESOCKET) { if(bool_temp==1) { int sock; @@ -128,6 +129,7 @@ CNullModem::CNullModem(Bitu id, CommandLine* cmd):CSerial (id, cmd) { } } } else { +#endif LOG_MSG("Serial%d: socket inheritance not supported on this platform.", COMNUMBER); return; diff --git a/src/hardware/serialport/softmodem.cpp b/src/hardware/serialport/softmodem.cpp index 28c52eb..460b758 100644 --- a/src/hardware/serialport/softmodem.cpp +++ b/src/hardware/serialport/softmodem.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: softmodem.cpp,v 1.7 2007/01/13 08:35:49 qbix79 Exp $ */ +/* $Id: softmodem.cpp,v 1.8 2007/07/19 18:58:39 c2woody Exp $ */ #include "dosbox.h" @@ -90,7 +90,13 @@ void CSerialModem::handleUpperEvent(Bit16u type) { if(tqueue->left() < 2) { CSerial::setCTS(false); } - } else LOG_MSG("MODEM: TX Buffer overflow!"); + } else { + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("MODEM: TX Buffer overflow!"); + } + } ByteTransmitted(); break; diff --git a/src/hardware/serialport/softmodem.h b/src/hardware/serialport/softmodem.h index a937ee6..9311f44 100644 --- a/src/hardware/serialport/softmodem.h +++ b/src/hardware/serialport/softmodem.h @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: softmodem.h,v 1.7 2007/01/13 08:35:49 qbix79 Exp $ */ +/* $Id: softmodem.h,v 1.8 2007/07/19 18:58:39 c2woody Exp $ */ #ifndef DOSBOX_SERIALMODEM_H #define DOSBOX_SERIALMODEM_H @@ -73,7 +73,11 @@ public: void addb(Bit8u _val) { if(used>=size) { - LOG_MSG("FIFO Overflow!"); + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("MODEM: FIFO Overflow! (addb)"); + } return; } //assert(usedsize) { - LOG_MSG("FIFO Overflow!"); + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("MODEM: FIFO Overflow! (adds len %d)",_len); + } return; } @@ -100,7 +108,11 @@ public: } Bit8u getb(void) { if (!used) { - LOG_MSG("MODEM: FIFO UNDERFLOW!"); + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("MODEM: FIFO UNDERFLOW! (getb)"); + } return data[pos]; } Bitu where=pos; @@ -111,7 +123,11 @@ public: } void gets(Bit8u * _str,Bitu _len) { if (!used) { - LOG_MSG("MODEM: FIFO UNDERFLOW!"); + static Bits lcount=0; + if (lcount<1000) { + lcount++; + LOG_MSG("MODEM: FIFO UNDERFLOW! (gets len %d)",_len); + } return; } //assert(used>=_len); diff --git a/src/hardware/tandy_sound.cpp b/src/hardware/tandy_sound.cpp index ab48087..23d1042 100644 --- a/src/hardware/tandy_sound.cpp +++ b/src/hardware/tandy_sound.cpp @@ -106,7 +106,7 @@ static void SN76496Write(Bitu port,Bitu data,Bitu iolen) { case 2: /* tone 1 : frequency */ case 4: /* tone 2 : frequency */ R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (R->Period[c] == 0) R->Period[c] = 0x3fe; if (r == 4) { /* update noise shift frequency */ @@ -129,8 +129,8 @@ static void SN76496Write(Bitu port,Bitu data,Bitu iolen) { R->Period[3] = (n == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+n)); /* reset noise shifter */ - R->RNG = NG_PRESET; - R->Output[3] = R->RNG & 1; +// R->RNG = NG_PRESET; +// R->Output[3] = R->RNG & 1; } break; } @@ -147,7 +147,7 @@ static void SN76496Write(Bitu port,Bitu data,Bitu iolen) { case 4: /* tone 2 : frequency */ R->Register[r] = (R->Register[r] & 0x0f) | ((data & 0x3f) << 4); R->Period[c] = R->UpdateStep * R->Register[r]; - if (R->Period[c] == 0) R->Period[c] = R->UpdateStep; + if (R->Period[c] == 0) R->Period[c] = 0x3fe; if (r == 4) { /* update noise shift frequency */ diff --git a/src/hardware/timer.cpp b/src/hardware/timer.cpp index c1307a5..7cc0c4a 100644 --- a/src/hardware/timer.cpp +++ b/src/hardware/timer.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: timer.cpp,v 1.42 2007/01/13 09:57:25 qbix79 Exp $ */ +/* $Id: timer.cpp,v 1.44 2007/06/12 20:22:08 c2woody Exp $ */ #include #include "dosbox.h" @@ -57,6 +57,7 @@ struct PIT_Block { }; static PIT_Block pit[3]; +static bool gate2; static Bit8u latched_timerstatus; // the timer status can not be overwritten until it is read or the timer was @@ -68,7 +69,7 @@ static void PIT0_Event(Bitu /*val*/) { if (pit[0].mode != 0) { pit[0].start += pit[0].delay; double error = pit[0].start - PIC_FullIndex(); - PIC_AddEvent(PIT0_Event,pit[0].delay + error); + PIC_AddEvent(PIT0_Event,(float)(pit[0].delay + error)); } } @@ -124,6 +125,10 @@ static void counter_latch(Bitu counter) { /* Fill the read_latch of the selected counter with current count */ PIT_Block * p=&pit[counter]; p->go_read_latch=false; + + //If gate2 is disabled don't update the read_latch + if(counter == 2 && !gate2) return; + double index=PIC_FullIndex()-p->start; switch (p->mode) { case 4: /* Software Triggered Strobe */ @@ -197,6 +202,7 @@ static void write_latch(Bitu port,Bitu val,Bitu /*iolen*/) { switch (counter) { case 0x00: /* Timer hooked to IRQ 0 */ if (p->new_mode || p->mode == 0 ) { + if(p->mode==0) PIC_RemoveEvents(PIT0_Event); // DoWhackaDo demo PIC_AddEvent(PIT0_Event,p->delay); } else LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer set without new control word"); LOG(LOG_PIT,LOG_NORMAL)("PIT 0 Timer at %.2f Hz mode %d",1000.0/p->delay,p->mode); @@ -262,15 +268,15 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { case 0: case 1: case 2: - pit[latch].bcd = (val&1)>0; - if (val & 1) { - if(pit[latch].cntr>=9999) pit[latch].cntr=9999; - } - if ((val & 0x30) == 0) { /* Counter latch command */ counter_latch(latch); } else { + pit[latch].bcd = (val&1)>0; + if (val & 1) { + if(pit[latch].cntr>=9999) pit[latch].cntr=9999; + } + // Timer is being reprogrammed, unlock the status if(pit[latch].counterstatus_set) { pit[latch].counterstatus_set=false; @@ -326,6 +332,33 @@ static void write_p43(Bitu /*port*/,Bitu val,Bitu /*iolen*/) { } } +void TIMER_SetGate2(bool in) { + //No changes if gate doesn't change + if(gate2 == in) return; + Bit8u & mode=pit[2].mode; + switch(mode) { + case 0: + if(in) pit[2].start = PIC_FullIndex(); + else { + //Fill readlatch and store it. + counter_latch(2); + pit[2].cntr = pit[2].read_latch; + } + break; + case 2: + case 3: + //If gate is enabled restart counting. If disable store the current read_latch + if(in) pit[2].start = PIC_FullIndex(); + else counter_latch(2); + break; + case 1: + case 4: + case 5: + LOG(LOG_MISC,LOG_WARN)("unsupported gate 2 mode %x",mode); + break; + } + gate2 = in; //Set it here so the counter_latch above works +} class TIMER:public Module_base{ private: @@ -374,6 +407,7 @@ public: pit[2].delay=(1000.0f/((float)PIT_TICK_RATE/(float)pit[2].cntr)); latched_timerstatus_locked=false; + gate2 = true; PIC_AddEvent(PIT0_Event,pit[0].delay); } ~TIMER(){ diff --git a/src/hardware/vga.cpp b/src/hardware/vga.cpp index b6d0f66..f8e4d95 100644 --- a/src/hardware/vga.cpp +++ b/src/hardware/vga.cpp @@ -84,7 +84,8 @@ void VGA_SetClock(Bitu which,Bitu target) { Bits err; } best; best.err=target; - Bitu n,m,r; + Bitu n,r; + Bits m; for (r = 0; r <= 3; r++) { Bitu f_vco = target * (1 << r); diff --git a/src/hardware/vga_dac.cpp b/src/hardware/vga_dac.cpp index 9aee884..955a6cb 100644 --- a/src/hardware/vga_dac.cpp +++ b/src/hardware/vga_dac.cpp @@ -139,6 +139,7 @@ static void write_p3c9(Bitu port,Bitu val,Bitu iolen) { break; default: LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + break; }; } @@ -161,6 +162,8 @@ static Bitu read_p3c9(Bitu port,Bitu iolen) { break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day + ret=0; + break; } return ret; } diff --git a/src/hardware/vga_draw.cpp b/src/hardware/vga_draw.cpp index 6a79b16..64f0baa 100644 --- a/src/hardware/vga_draw.cpp +++ b/src/hardware/vga_draw.cpp @@ -380,7 +380,7 @@ static Bit8u * VGA_Draw_LIN32_Line_HWMouse(Bitu vidstart, Bitu line) { static Bit32u FontMask[2]={0xffffffff,0x0}; static Bit8u * VGA_TEXT_Draw_Line(Bitu vidstart, Bitu line) { - Bitu font_addr; + Bits font_addr; Bit32u * draw=(Bit32u *)TempLine; const Bit8u *vidmem = &vga.tandy.draw_base[vidstart]; for (Bitu cx=0;cx> 1; - if (font_addr>=0 && font_addr=0 && font_addr<(Bits)vga.draw.blocks) { if (linevga.draw.cursor.eline) goto skip_cursor; draw=(Bit32u *)&TempLine[font_addr*8]; @@ -579,8 +579,8 @@ static void VGA_VerticalTimer(Bitu val) { break; } //VGA_DrawPart( vga.draw.parts_lines ); - PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts,vga.draw.parts_lines); -// PIC_AddEvent(VGA_DrawPart,vga.draw.delay.parts/2,vga.draw.parts_lines); //Else tearline in Tyrian and second reality + PIC_AddEvent(VGA_DrawPart,(float)vga.draw.delay.parts,vga.draw.parts_lines); +// PIC_AddEvent(VGA_DrawPart,(float)(vga.draw.delay.parts/2),vga.draw.parts_lines); //Else tearline in Tyrian and second reality } void VGA_CheckScanLength(void) { @@ -983,7 +983,7 @@ void VGA_SetupDrawing(Bitu val) { #endif RENDER_SetSize(width,height,bpp,fps,aspect_ratio,doublewidth,doubleheight); vga.draw.delay.framestart = PIC_FullIndex(); - PIC_AddEvent( VGA_VerticalTimer , vga.draw.delay.vtotal ); + PIC_AddEvent( VGA_VerticalTimer , (float)vga.draw.delay.vtotal ); } }; diff --git a/src/hardware/vga_memory.cpp b/src/hardware/vga_memory.cpp index 2588264..19a573f 100644 --- a/src/hardware/vga_memory.cpp +++ b/src/hardware/vga_memory.cpp @@ -96,6 +96,8 @@ INLINE static Bit32u ModeOperation(Bit8u val) { break; default: LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:Unsupported write mode %d",vga.config.write_mode); + full=0; + break; } return full; } diff --git a/src/hardware/vga_misc.cpp b/src/hardware/vga_misc.cpp index 9306acf..58ae7cd 100644 --- a/src/hardware/vga_misc.cpp +++ b/src/hardware/vga_misc.cpp @@ -22,7 +22,6 @@ #include "vga.h" #include -static Bit8u flip=0; void vga_write_p3d4(Bitu port,Bitu val,Bitu iolen); Bitu vga_read_p3d4(Bitu port,Bitu iolen); @@ -38,10 +37,9 @@ static Bitu vga_read_p3da(Bitu port,Bitu iolen) { vga.internal.attrindex=false; vga.tandy.pcjr_flipflop=false; - double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); - switch (machine) { case MCH_HERC: + { // 3BAh (R): Status Register // bit 0 Horizontal sync // 3 Video signal @@ -49,11 +47,13 @@ static Bitu vga_read_p3da(Bitu port,Bitu iolen) { if(timeInFrame >= vga.draw.delay.vrstart && timeInFrame <= vga.draw.delay.vrend) retval |= 0x80; + double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); if(timeInLine >= vga.draw.delay.hrstart && timeInLine <= vga.draw.delay.hrend) retval |= 1; retval |= 0x10; //Hercules ident break; + } default: // 3DAh (R): Status Register // bit 0 Horizontal or Vertical blanking @@ -62,12 +62,15 @@ static Bitu vga_read_p3da(Bitu port,Bitu iolen) { if(timeInFrame >= vga.draw.delay.vrstart && timeInFrame <= vga.draw.delay.vrend) retval |= 8; - if(timeInFrame >= vga.draw.delay.vblkstart && - timeInFrame <= vga.draw.delay.vblkend) - retval |= 1; - else if(timeInLine >= vga.draw.delay.hblkstart && - timeInLine <= vga.draw.delay.hblkend) + if(timeInFrame >= vga.draw.delay.vdend) retval |= 1; + else { + double timeInLine=fmod(timeInFrame,vga.draw.delay.htotal); + if(timeInLine >= (vga.draw.delay.hblkstart) && + timeInLine <= vga.draw.delay.hblkend){ + retval |= 1; + } + } } return retval; } diff --git a/src/hardware/vga_s3.cpp b/src/hardware/vga_s3.cpp index 3812429..4f2d762 100644 --- a/src/hardware/vga_s3.cpp +++ b/src/hardware/vga_s3.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: vga_s3.cpp,v 1.6 2007/01/08 19:45:40 qbix79 Exp $ */ +/* $Id: vga_s3.cpp,v 1.8 2007/06/28 16:02:27 c2woody Exp $ */ #include "dosbox.h" #include "inout.h" @@ -303,7 +303,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) { VGA_SetupHandlers(); break; default: - LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:SEQ:Write to illegal index %2X", reg ); + LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC:Write to illegal index %2X", reg ); break; } } @@ -375,6 +375,7 @@ Bitu SVGA_S3_ReadCRTC( Bitu reg, Bitu iolen) { } void SVGA_S3_WriteSEQ(Bitu reg,Bitu val,Bitu iolen) { + if (reg>0x8 && vga.s3.pll.lock!=0x6) return; switch (reg) { case 0x08: vga.s3.pll.lock=val; @@ -405,6 +406,10 @@ void SVGA_S3_WriteSEQ(Bitu reg,Bitu val,Bitu iolen) { Bitu SVGA_S3_ReadSEQ(Bitu reg,Bitu iolen) { /* S3 specific group */ + if (reg>0x8 && vga.s3.pll.lock!=0x6) { + if (reg<0x1b) return 0; + else return reg; + } switch (reg) { case 0x08: /* PLL Unlock */ return vga.s3.pll.lock; diff --git a/src/hardware/vga_seq.cpp b/src/hardware/vga_seq.cpp index 6ca6634..04d29aa 100644 --- a/src/hardware/vga_seq.cpp +++ b/src/hardware/vga_seq.cpp @@ -31,7 +31,6 @@ void write_p3c4(Bitu port,Bitu val,Bitu iolen) { }; void write_p3c5(Bitu port,Bitu val,Bitu iolen) { - if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return; // LOG_MSG("SEQ WRITE reg %X val %X",seq(index),val); switch(seq(index)) { case 0: /* Reset */ @@ -114,7 +113,6 @@ void write_p3c5(Bitu port,Bitu val,Bitu iolen) { Bitu read_p3c5(Bitu port,Bitu iolen) { // LOG_MSG("VGA:SEQ:Read from index %2X",seq(index)); - if (seq(index)>0x8 && vga.s3.pll.lock!=0x6) return seq(index); switch(seq(index)) { case 0: /* Reset */ return seq(reset); diff --git a/src/hardware/ymf262.c b/src/hardware/ymf262.c index e9bd41f..6e044fc 100644 --- a/src/hardware/ymf262.c +++ b/src/hardware/ymf262.c @@ -280,51 +280,51 @@ static const int slot_array[32]= /* key scale level */ /* table is 3dB/octave , DV converts this into 6dB/octave */ /* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */ -#define DV (0.1875/2.0) +#define SC(x) ((UINT32)((x)/(0.1875/2.0))) static const UINT32 ksl_tab[8*16]= { /* OCT 0 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), /* OCT 1 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV, - 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(0.750), SC(1.125), SC(1.500), + SC(1.875), SC(2.250), SC(2.625), SC(3.000), /* OCT 2 */ - 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV, - 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV, - 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV, - 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(0.000), + SC(0.000), SC(1.125), SC(1.875), SC(2.625), + SC(3.000), SC(3.750), SC(4.125), SC(4.500), + SC(4.875), SC(5.250), SC(5.625), SC(6.000), /* OCT 3 */ - 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV, - 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV, - 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV, - 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV, + SC(0.000), SC(0.000), SC(0.000), SC(1.875), + SC(3.000), SC(4.125), SC(4.875), SC(5.625), + SC(6.000), SC(6.750), SC(7.125), SC(7.500), + SC(7.875), SC(8.250), SC(8.625), SC(9.000), /* OCT 4 */ - 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV, - 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV, - 9.000/DV, 9.750/DV,10.125/DV,10.500/DV, - 10.875/DV,11.250/DV,11.625/DV,12.000/DV, + SC(0.000), SC(0.000), SC(3.000), SC(4.875), + SC(6.000), SC(7.125), SC(7.875), SC(8.625), + SC(9.000), SC(9.750),SC(10.125),SC(10.500), + SC(10.875),SC(11.250),SC(11.625),SC(12.000), /* OCT 5 */ - 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV, - 9.000/DV,10.125/DV,10.875/DV,11.625/DV, - 12.000/DV,12.750/DV,13.125/DV,13.500/DV, - 13.875/DV,14.250/DV,14.625/DV,15.000/DV, + SC(0.000), SC(3.000), SC(6.000), SC(7.875), + SC(9.000),SC(10.125),SC(10.875),SC(11.625), + SC(12.000),SC(12.750),SC(13.125),SC(13.500), + SC(13.875),SC(14.250),SC(14.625),SC(15.000), /* OCT 6 */ - 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV, - 12.000/DV,13.125/DV,13.875/DV,14.625/DV, - 15.000/DV,15.750/DV,16.125/DV,16.500/DV, - 16.875/DV,17.250/DV,17.625/DV,18.000/DV, + SC(0.000), SC(6.000), SC(9.000),SC(10.875), + SC(12.000),SC(13.125),SC(13.875),SC(14.625), + SC(15.000),SC(15.750),SC(16.125),SC(16.500), + SC(16.875),SC(17.250),SC(17.625),SC(18.000), /* OCT 7 */ - 0.000/DV, 9.000/DV,12.000/DV,13.875/DV, - 15.000/DV,16.125/DV,16.875/DV,17.625/DV, - 18.000/DV,18.750/DV,19.125/DV,19.500/DV, - 19.875/DV,20.250/DV,20.625/DV,21.000/DV + SC(0.000), SC(9.000),SC(12.000),SC(13.875), + SC(15.000),SC(16.125),SC(16.875),SC(17.625), + SC(18.000),SC(18.750),SC(19.125),SC(19.500), + SC(19.875),SC(20.250),SC(20.625),SC(21.000) }; -#undef DV +#undef SC /* sustain level table (3dB per step) */ /* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ @@ -444,13 +444,13 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), /* multiple table */ -#define ML 2 +#define SC(x) ((UINT32)((x)*2)) static const UINT8 mul_tab[16]= { /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, - 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML + SC(0.50), SC(1.00), SC(2.00), SC(3.00), SC(4.00), SC(5.00), SC(6.00), SC(7.00), + SC(8.00), SC(9.00),SC(10.00),SC(10.00),SC(12.00),SC(12.00),SC(15.00),SC(15.00) }; -#undef ML +#undef SC /* TL_TAB_LEN is calculated as: @@ -1344,17 +1344,17 @@ static void OPL3_initalize(OPL3 *chip) /* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */ /* One entry from LFO_AM_TABLE lasts for 64 samples */ - chip->lfo_am_inc = (1.0 / 64.0 ) * (1<freqbase; + chip->lfo_am_inc = (UINT32)((1.0 / 64.0 ) * (1<freqbase); /* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */ - chip->lfo_pm_inc = (1.0 / 1024.0) * (1<freqbase; + chip->lfo_pm_inc = (UINT32)((1.0 / 1024.0) * (1<freqbase); /*logerror ("chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\n", chip->lfo_am_inc, chip->lfo_pm_inc);*/ /* Noise generator: a step takes 1 sample */ - chip->noise_f = (1.0 / 1.0) * (1<freqbase; + chip->noise_f = (UINT32)((1.0 / 1.0) * (1<freqbase); - chip->eg_timer_add = (1<freqbase; + chip->eg_timer_add = (UINT32)((1<freqbase); chip->eg_timer_overflow = ( 1 ) * (1<eg_timer_add, chip->eg_timer_overflow);*/ diff --git a/src/ints/bios.cpp b/src/ints/bios.cpp index 118e43c..8e63ad8 100644 --- a/src/ints/bios.cpp +++ b/src/ints/bios.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: bios.cpp,v 1.66 2007/02/22 08:33:15 qbix79 Exp $ */ +/* $Id: bios.cpp,v 1.68 2007/06/12 20:22:08 c2woody Exp $ */ #include "dosbox.h" #include "mem.h" @@ -364,7 +364,7 @@ static Bitu INT14_Handler(void) { if(reg_ah > 0x3 || reg_dx > 0x3) { // 0-3 serial port functions // and no more than 4 serial ports - LOG_MSG("BIOS INT14: Unhandled call AH=%2X DX=%4x",reg_dx); + LOG_MSG("BIOS INT14: Unhandled call AH=%2X DX=%4x",reg_ah,reg_dx); return CBRET_NONE; } @@ -981,7 +981,7 @@ void BIOS_SetComPorts(Bit16u baseaddr[]) { equipmentword &= (~0x0E00); equipmentword |= (portcount << 9); mem_writew(BIOS_CONFIGURATION,equipmentword); - CMOS_SetRegister(0x14,equipmentword); //Should be updated on changes + CMOS_SetRegister(0x14,(Bit8u)(equipmentword&0xff)); //Should be updated on changes } diff --git a/src/ints/bios_disk.cpp b/src/ints/bios_disk.cpp index e5967de..9214bd2 100644 --- a/src/ints/bios_disk.cpp +++ b/src/ints/bios_disk.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: bios_disk.cpp,v 1.33 2007/01/21 16:21:22 c2woody Exp $ */ +/* $Id: bios_disk.cpp,v 1.37 2007/07/14 16:42:38 c2woody Exp $ */ #include "dosbox.h" #include "callback.h" @@ -40,7 +40,7 @@ diskGeo DiskGeometryList[] = { {1200, 15, 2, 80, 2}, {1440, 18, 2, 80, 4}, {2880, 36, 2, 80, 6}, - {0, 0, 0 , 0}, + {0, 0, 0, 0, 0} }; Bitu call_int13; @@ -65,8 +65,8 @@ void updateDPT(void) { if(imageDiskList[2] != NULL) { PhysPt dp0physaddr=CALLBACK_PhysPointer(diskparm0); imageDiskList[2]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - phys_writew(dp0physaddr,tmpcyl); - phys_writeb(dp0physaddr+0x2,tmpheads); + phys_writew(dp0physaddr,(Bit16u)tmpcyl); + phys_writeb(dp0physaddr+0x2,(Bit8u)tmpheads); phys_writew(dp0physaddr+0x3,0); phys_writew(dp0physaddr+0x5,(Bit16u)-1); phys_writeb(dp0physaddr+0x7,0); @@ -74,15 +74,15 @@ void updateDPT(void) { phys_writeb(dp0physaddr+0x9,0); phys_writeb(dp0physaddr+0xa,0); phys_writeb(dp0physaddr+0xb,0); - phys_writew(dp0physaddr+0xc,tmpcyl); - phys_writeb(dp0physaddr+0xe,tmpsect); + phys_writew(dp0physaddr+0xc,(Bit16u)tmpcyl); + phys_writeb(dp0physaddr+0xe,(Bit8u)tmpsect); } if(imageDiskList[3] != NULL) { PhysPt dp1physaddr=CALLBACK_PhysPointer(diskparm1); imageDiskList[3]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - phys_writew(dp1physaddr,tmpcyl); - phys_writeb(dp1physaddr+0x2,tmpheads); - phys_writeb(dp1physaddr+0xe,tmpsect); + phys_writew(dp1physaddr,(Bit16u)tmpcyl); + phys_writeb(dp1physaddr+0x2,(Bit8u)tmpheads); + phys_writeb(dp1physaddr+0xe,(Bit8u)tmpsect); } } @@ -173,9 +173,9 @@ Bit8u imageDisk::Write_AbsoluteSector(Bit32u sectnum, void *data) { //LOG_MSG("Writing sectors to %ld at bytenum %d", sectnum, bytenum); fseek(diskimg,bytenum,SEEK_SET); - fwrite(data, sector_size, 1, diskimg); + size_t ret=fwrite(data, sector_size, 1, diskimg); - return 0x00; + return ((ret>0)?0x00:0x05); } @@ -199,7 +199,10 @@ imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHard Bitu i=0; bool founddisk = false; while (DiskGeometryList[i].ksize!=0x0) { - if (DiskGeometryList[i].ksize==imgSizeK) { + if ((DiskGeometryList[i].ksize==imgSizeK) || + (DiskGeometryList[i].ksize+1==imgSizeK)) { + if (DiskGeometryList[i].ksize!=imgSizeK) + LOG_MSG("ImageLoader: image file with additional data, might not load!"); founddisk = true; active = true; floppytype = i; @@ -222,7 +225,7 @@ imageDisk::imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHard equipment|=(numofdisks<<6); } else equipment|=1; mem_writew(BIOS_CONFIGURATION,equipment); - CMOS_SetRegister(0x14, equipment); + CMOS_SetRegister(0x14, (Bit8u)(equipment&0xff)); } } } @@ -244,7 +247,7 @@ void imageDisk::Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit8u imageDisk::GetBiosType(void) { if(!hardDrive) { - return DiskGeometryList[floppytype].biosval; + return (Bit8u)DiskGeometryList[floppytype].biosval; } else return 0; } @@ -298,11 +301,11 @@ static Bitu INT13_DiskHandler(void) { Bit16u segat, bufptr; Bit8u sectbuf[512]; Bitu drivenum; - int i,t; + Bitu i,t; last_drive = reg_dl; drivenum = GetDosDriveNumber(reg_dl); bool any_images = false; - for(Bitu i = 0;i < MAX_DISK_IMAGES;i++) { + for(i = 0;i < MAX_DISK_IMAGES;i++) { if(imageDiskList[i]) any_images=true; } @@ -436,16 +439,20 @@ static Bitu INT13_DiskHandler(void) { if(driveInactive(drivenum)) { last_status = 0x07; reg_ah = last_status; - CALLBACK_SCF(true); + CALLBACK_SCF(true); return CBRET_NONE; } reg_ax = 0x00; reg_bl = imageDiskList[drivenum]->GetBiosType(); Bit32u tmpheads, tmpcyl, tmpsect, tmpsize; imageDiskList[drivenum]->Get_Geometry(&tmpheads, &tmpcyl, &tmpsect, &tmpsize); - reg_ch = tmpcyl & 0xff; - reg_cl = (((tmpcyl >> 2) & 0xc0) | (tmpsect & 0x3f)); - reg_dh = tmpheads-1; + if (tmpcyl==0) LOG(LOG_BIOS,LOG_ERROR)("INT13 DrivParm: cylinder count zero!"); + else tmpcyl--; // cylinder count -> max cylinder + if (tmpheads==0) LOG(LOG_BIOS,LOG_ERROR)("INT13 DrivParm: head count zero!"); + else tmpheads--; // head count -> max head + reg_ch = (Bit8u)(tmpcyl & 0xff); + reg_cl = (Bit8u)(((tmpcyl >> 2) & 0xc0) | (tmpsect & 0x3f)); + reg_dh = (Bit8u)tmpheads; last_status = 0x00; if (reg_dl&0x80) { // harddisks reg_dl = 0; diff --git a/src/ints/int10.cpp b/src/ints/int10.cpp index 3cab386..ea495db 100644 --- a/src/ints/int10.cpp +++ b/src/ints/int10.cpp @@ -299,6 +299,21 @@ graphics_chars: reg_bl=3; //256 kb reg_cx=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F; break; + case 0x20: /* Set alternate printscreen */ + break; + case 0x30: /* Select vertical resolution */ + case 0x32: /* Video adressing */ + LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); + reg_al=0x12; //fake a success call + break; + case 0x31: /* Palette loading on modeset */ + { + Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xf7; + if (reg_al&1) temp|=8; // enable if al=0 + real_writeb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL,temp); + reg_al=0x12; + break; + } case 0x33: /* SWITCH GRAY-SCALE SUMMING */ { Bit8u temp = real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 0xfd; @@ -324,7 +339,8 @@ graphics_chars: break; default: LOG(LOG_INT10,LOG_ERROR)("Function 12:Call %2X not handled",reg_bl); - reg_al=0x12; //Always fake a success call + reg_al=0x12; // wrong!? + break; } break; case 0x13: /* Write String */ diff --git a/src/ints/int10_char.cpp b/src/ints/int10_char.cpp index 666c81d..a027191 100644 --- a/src/ints/int10_char.cpp +++ b/src/ints/int10_char.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_char.cpp,v 1.49 2007/01/08 19:45:41 qbix79 Exp $ */ +/* $Id: int10_char.cpp,v 1.50 2007/06/12 20:22:08 c2woody Exp $ */ /* Character displaying moving functions */ @@ -534,7 +534,7 @@ void INT10_WriteChar(Bit8u chr,Bit8u attr,Bit8u page,Bit16u count,bool showattr) Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); - BIOS_NCOLS;BIOS_NROWS; + BIOS_NCOLS; while (count>0) { WriteChar(cur_col,cur_row,page,chr,attr,showattr); count--; @@ -600,7 +600,6 @@ void INT10_TeletypeOutput(Bit8u chr,Bit8u attr) { } void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,Bit16u count,Bit8u page) { - BIOS_NCOLS;BIOS_NROWS; Bit8u cur_row=CURSOR_POS_ROW(page); Bit8u cur_col=CURSOR_POS_COL(page); diff --git a/src/ints/int10_memory.cpp b/src/ints/int10_memory.cpp index 7e8d74e..2fd73d0 100644 --- a/src/ints/int10_memory.cpp +++ b/src/ints/int10_memory.cpp @@ -113,6 +113,9 @@ void INT10_SetupRomMemory(void) { } RealSetVec(0x1F,int10.rom.font_8_second); + if (IS_TANDY_ARCH) { + RealSetVec(0x44,int10.rom.font_8_first); + } if (machine == MCH_VGA) { //EGA/VGA. Just to be safe //Reserve checksum location checksumlocation = int10.rom.used++; diff --git a/src/ints/int10_misc.cpp b/src/ints/int10_misc.cpp index 0c56c2d..7b31e24 100644 --- a/src/ints/int10_misc.cpp +++ b/src/ints/int10_misc.cpp @@ -218,7 +218,7 @@ void INT10_EGA_RIL_ReadRegisterRange(Bit8u & bl, Bit8u ch, Bit8u cl, Bit16u dx, LOG(LOG_INT10,LOG_ERROR)("EGA RIL range read with port %x called",port); } else { if(chregs) cl=regs-ch; + if ((Bitu)ch+cl>regs) cl=(Bit8u)(regs-ch); for (Bitu i=0; iregs) cl=regs-ch; + if ((Bitu)ch+cl>regs) cl=(Bit8u)(regs-ch); if(port == 0x3c0) { IO_Read(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS) + 6); for (Bitu i=0; ivdispend+1) << 8); //Maximum scanline Bit8u scanline,crtpage; + scanline=8; switch(CurMode->type) { case M_TEXT: if (machine==MCH_HERC) scanline=14; @@ -873,64 +874,69 @@ att_text16: break; } IO_Read(mono_mode ? 0x3ba : 0x3da); - for (i=0;itype) { - case M_EGA: - if (CurMode->mode>0xf) goto dac_text16; - else if (CurMode->mode==0xf) goto dac_mtext16; - for (i=0;i<64;i++) { - IO_Write(0x3c9,ega_palette[i][0]); - IO_Write(0x3c9,ega_palette[i][1]); - IO_Write(0x3c9,ega_palette[i][2]); + if ((modeset_ctl & 8)==0) { + for (i=0;imode==7) { -dac_mtext16: + IO_Write(0x3c0,0x20); IO_Write(0x3c0,0x00); //Disable palette access + IO_Write(0x3c6,0xff); //Reset Pelmask + /* Setup the DAC */ + IO_Write(0x3c8,0); + switch (CurMode->type) { + case M_EGA: + if (CurMode->mode>0xf) goto dac_text16; + else if (CurMode->mode==0xf) goto dac_mtext16; for (i=0;i<64;i++) { - IO_Write(0x3c9,mtext_palette[i][0]); - IO_Write(0x3c9,mtext_palette[i][1]); - IO_Write(0x3c9,mtext_palette[i][2]); + IO_Write(0x3c9,ega_palette[i][0]); + IO_Write(0x3c9,ega_palette[i][1]); + IO_Write(0x3c9,ega_palette[i][2]); + } + break; + case M_CGA2: + case M_CGA4: + case M_TANDY16: + for (i=0;i<64;i++) { + IO_Write(0x3c9,cga_palette_2[i][0]); + IO_Write(0x3c9,cga_palette_2[i][1]); + IO_Write(0x3c9,cga_palette_2[i][2]); + } + break; + case M_TEXT: + if (CurMode->mode==7) { +dac_mtext16: + for (i=0;i<64;i++) { + IO_Write(0x3c9,mtext_palette[i][0]); + IO_Write(0x3c9,mtext_palette[i][1]); + IO_Write(0x3c9,mtext_palette[i][2]); + } + break; + } +dac_text16: + for (i=0;i<64;i++) { + IO_Write(0x3c9,text_palette[i][0]); + IO_Write(0x3c9,text_palette[i][1]); + IO_Write(0x3c9,text_palette[i][2]); + } + break; + case M_VGA: + case M_LIN8: + case M_LIN16: + for (i=0;i<256;i++) { + IO_Write(0x3c9,vga_palette[i][0]); + IO_Write(0x3c9,vga_palette[i][1]); + IO_Write(0x3c9,vga_palette[i][2]); } break; } -dac_text16: - for (i=0;i<64;i++) { - IO_Write(0x3c9,text_palette[i][0]); - IO_Write(0x3c9,text_palette[i][1]); - IO_Write(0x3c9,text_palette[i][2]); - } - break; - case M_VGA: - case M_LIN8: - case M_LIN16: - for (i=0;i<256;i++) { - IO_Write(0x3c9,vga_palette[i][0]); - IO_Write(0x3c9,vga_palette[i][1]); - IO_Write(0x3c9,vga_palette[i][2]); - } - break; - } - if (machine==MCH_VGA) { - /* check if gray scale summing is enabled */ - if (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 2) { - INT10_PerformGrayScaleSumming(0,256); + if (machine==MCH_VGA) { + /* check if gray scale summing is enabled */ + if (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 2) { + INT10_PerformGrayScaleSumming(0,256); + } } + } else { + IO_Write(0x3c0,0x20); //Disable palette access } /* Setup some special stuff for different modes */ Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE); @@ -989,6 +995,7 @@ dac_text16: } IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing + IO_Write(crtc_base,0x53);IO_Write(crtc_base+1,0x0); //Disable MMIO IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2 diff --git a/src/ints/int10_pal.cpp b/src/ints/int10_pal.cpp index 9544f86..810343c 100644 --- a/src/ints/int10_pal.cpp +++ b/src/ints/int10_pal.cpp @@ -210,7 +210,7 @@ void INT10_GetPelMask(Bit8u & mask) { } void INT10_SetBackgroundBorder(Bit8u val) { - Bitu temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); + Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); temp=(temp & 0xe0) | (val & 0x1f); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); if (machine == MCH_CGA || IS_TANDY_ARCH) @@ -233,7 +233,7 @@ void INT10_SetBackgroundBorder(Bit8u val) { } void INT10_SetColorSelect(Bit8u val) { - Bitu temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); + Bit8u temp=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL); temp=(temp & 0xdf) | ((val & 1) ? 0x20 : 0x0); real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,temp); if (machine == MCH_CGA || IS_TANDY_ARCH) diff --git a/src/ints/int10_put_pixel.cpp b/src/ints/int10_put_pixel.cpp index c76adf4..b6445ea 100644 --- a/src/ints/int10_put_pixel.cpp +++ b/src/ints/int10_put_pixel.cpp @@ -21,8 +21,8 @@ #include "inout.h" #include "int10.h" -static Bit8u cga_masks[4]={~192U,~48U,~12U,~3U}; -static Bit8u cga_masks2[8]={~128U,~64U,~32U,~16U,~8U,~4U,~2U,~1U}; +static Bit8u cga_masks[4]={0x3f,0xcf,0xf3,0xfc}; +static Bit8u cga_masks2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; void INT10_PutPixel(Bit16u x,Bit16u y,Bit8u page,Bit8u color) { switch (CurMode->type) { diff --git a/src/ints/int10_vesa.cpp b/src/ints/int10_vesa.cpp index 783a9f7..c266d6d 100644 --- a/src/ints/int10_vesa.cpp +++ b/src/ints/int10_vesa.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: int10_vesa.cpp,v 1.26 2007/01/24 16:29:53 harekiet Exp $ */ +/* $Id: int10_vesa.cpp,v 1.27 2007/06/12 20:22:09 c2woody Exp $ */ #include #include @@ -228,7 +228,7 @@ Bit8u VESA_SetSVGAMode(Bit16u mode) { }; Bit8u VESA_GetSVGAMode(Bit16u & mode) { - mode=CurMode->mode; + mode=(Bit16u)(CurMode->mode); return 0x00; } diff --git a/src/ints/mouse.cpp b/src/ints/mouse.cpp index 64642b9..0a0d867 100644 --- a/src/ints/mouse.cpp +++ b/src/ints/mouse.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: mouse.cpp,v 1.66 2007/01/08 19:45:41 qbix79 Exp $ */ +/* $Id: mouse.cpp,v 1.69 2007/06/12 20:22:09 c2woody Exp $ */ #include #include @@ -34,7 +34,7 @@ #include "bios.h" -static Bitu call_int33,call_int74,int74_ret_callback; +static Bitu call_int33,call_int74,int74_ret_callback,call_mouse_bd; static Bit16u ps2cbseg,ps2cbofs; static bool useps2callback,ps2callbackinit; static Bit16u call_ps2; @@ -236,12 +236,12 @@ void DrawCursorText() Bit16u result; ReadCharAttr(mouse.backposx,mouse.backposy,0,&result); - mouse.backData[0] = result & 0xFF; - mouse.backData[1] = result>>8; + mouse.backData[0] = (Bit8u)(result & 0xFF); + mouse.backData[1] = (Bit8u)(result>>8); mouse.background = true; // Write Cursor result = (result & mouse.textAndMask) ^ mouse.textXorMask; - WriteChar(mouse.backposx,mouse.backposy,0,result&0xFF,result>>8,true); + WriteChar(mouse.backposx,mouse.backposy,0,(Bit8u)(result&0xFF),(Bit8u)(result>>8),true); }; // *************************************************************************** @@ -508,8 +508,8 @@ static void SetSensitivity(Bit16s px, Bit16s py){ if ((px!=0) && (py!=0)) { px--; //Inspired by cutemouse py--; //Although their cursor update routine is far more complex then ours - mouse.senv_x=(static_cast(px)*px)/3600.0 +1.0/3.0; - mouse.senv_y=(static_cast(py)*py)/3600.0 +1.0/3.0; + mouse.senv_x=(static_cast(px)*px)/3600.0f +1.0f/3.0f; + mouse.senv_y=(static_cast(py)*py)/3600.0f +1.0f/3.0f; } }; @@ -862,6 +862,65 @@ static Bitu INT33_Handler(void) { return CBRET_NONE; } +static Bitu MOUSE_BD_Handler(void) { + // the stack contains offsets to register values + Bit16u raxpt=real_readw(SegValue(ss),reg_sp+0x0a); + Bit16u rbxpt=real_readw(SegValue(ss),reg_sp+0x08); + Bit16u rcxpt=real_readw(SegValue(ss),reg_sp+0x06); + Bit16u rdxpt=real_readw(SegValue(ss),reg_sp+0x04); + + // read out the actual values, registers ARE overwritten + Bit16u rax=real_readw(SegValue(ds),raxpt); + reg_ax=rax; + reg_bx=real_readw(SegValue(ds),rbxpt); + reg_cx=real_readw(SegValue(ds),rcxpt); + reg_dx=real_readw(SegValue(ds),rdxpt); +// LOG_MSG("MOUSE BD: %04X %X %X %X %d %d",reg_ax,reg_bx,reg_cx,reg_dx,POS_X,POS_Y); + + // some functions are treated in a special way (additional registers) + switch (rax) { + case 0x09: /* Define GFX Cursor */ + case 0x16: /* Save driver state */ + case 0x17: /* load driver state */ + SegSet16(es,SegValue(ds)); + break; + case 0x0c: /* Define interrupt subroutine parameters */ + case 0x14: /* Exchange event-handler */ + if (reg_bx!=0) SegSet16(es,reg_bx); + else SegSet16(es,SegValue(ds)); + break; + case 0x10: /* Define screen region for updating */ + reg_cx=real_readw(SegValue(ds),rdxpt); + reg_dx=real_readw(SegValue(ds),rdxpt+2); + reg_si=real_readw(SegValue(ds),rdxpt+4); + reg_di=real_readw(SegValue(ds),rdxpt+6); + break; + default: + break; + } + + INT33_Handler(); + + // save back the registers, too + real_writew(SegValue(ds),raxpt,reg_ax); + real_writew(SegValue(ds),rbxpt,reg_bx); + real_writew(SegValue(ds),rcxpt,reg_cx); + real_writew(SegValue(ds),rdxpt,reg_dx); + switch (rax) { + case 0x1f: /* Disable Mousedriver */ + real_writew(SegValue(ds),rbxpt,SegValue(es)); + break; + case 0x14: /* Exchange event-handler */ + real_writew(SegValue(ds),rcxpt,SegValue(es)); + break; + default: + break; + } + + reg_ax=rax; + return CBRET_NONE; +} + static Bitu INT74_Handler(void) { if (mouse.events>0) { mouse.events--; @@ -902,9 +961,23 @@ Bitu MOUSE_UserInt_CB_Handler(void) { void MOUSE_Init(Section* sec) { // Callback for mouse interrupt 0x33 call_int33=CALLBACK_Allocate(); - CALLBACK_Setup(call_int33,&INT33_Handler,CB_IRET,"Mouse"); +// RealPt i33loc=RealMake(CB_SEG+1,(call_int33*CB_SIZE)-0x10); + RealPt i33loc=RealMake(DOS_GetMemory(0x1)-1,0x10); + CALLBACK_Setup(call_int33,&INT33_Handler,CB_MOUSE,Real2Phys(i33loc),"Mouse"); // Wasteland needs low(seg(int33))!=0 and low(ofs(int33))!=0 - real_writed(0,0x33<<2,RealMake(CB_SEG+1,(call_int33*CB_SIZE)-0x10)); + real_writed(0,0x33<<2,i33loc); + + call_mouse_bd=CALLBACK_Allocate(); + CALLBACK_Setup(call_mouse_bd,&MOUSE_BD_Handler,CB_RETF8, + PhysMake(RealSeg(i33loc),RealOff(i33loc)+2),"MouseBD"); + // pseudocode for CB_MOUSE (including the special backdoor entry point): + // jump near i33hd + // callback MOUSE_BD_Handler + // retf 8 + // label i33hd: + // callback INT33_Handler + // iret + // Callback for ps2 irq call_int74=CALLBACK_Allocate(); diff --git a/src/ints/xms.cpp b/src/ints/xms.cpp index d426127..a909e91 100644 --- a/src/ints/xms.cpp +++ b/src/ints/xms.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: xms.cpp,v 1.46 2007/01/08 21:40:15 qbix79 Exp $ */ +/* $Id: xms.cpp,v 1.49 2007/06/25 18:45:48 qbix79 Exp $ */ #include #include @@ -81,7 +81,9 @@ struct XMS_Block { bool free; }; -#pragma pack (push,1) +#ifdef _MSC_VER +#pragma pack (1) +#endif struct XMS_MemMove{ Bit32u length; Bit16u src_handle; @@ -96,7 +98,10 @@ struct XMS_MemMove{ } dest; } GCC_ATTRIBUTE(packed); -#pragma pack (pop) +#ifdef _MSC_VER +#pragma pack () +#endif + Bitu XMS_EnableA20(bool enable) { @@ -229,7 +234,7 @@ Bitu XMS_GetHandleInformation(Bitu handle, Bit8u& lockCount, Bit8u& numFree, Bit for (Bitu i=1;i #include @@ -54,11 +54,12 @@ static std::vector internal_progs; void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) { Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK memcpy(comdata,&exe_block,sizeof(exe_block)); - comdata[CB_POS]=call_program&0xff; - comdata[CB_POS+1]=(call_program>>8)&0xff; + comdata[CB_POS]=(Bit8u)(call_program&0xff); + comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff); /* Copy save the pointer in the vector and save it's index */ - Bit8u index = internal_progs.size(); + if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",internal_progs.size()); + Bit8u index = (Bit8u)internal_progs.size(); internal_progs.push_back(main); memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index)); @@ -329,7 +330,7 @@ static void CONFIG_ProgramStart(Program * * make) { } -void PROGRAMS_Init(Section* sec) { +void PROGRAMS_Init(Section* /*sec*/) { /* Setup a special callback to start virtual programs */ call_program=CALLBACK_Allocate(); CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program"); diff --git a/src/misc/setup.cpp b/src/misc/setup.cpp index 5be52ff..b8b572e 100644 --- a/src/misc/setup.cpp +++ b/src/misc/setup.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: setup.cpp,v 1.38 2007/01/08 19:45:41 qbix79 Exp $ */ +/* $Id: setup.cpp,v 1.40 2007/06/27 14:51:30 qbix79 Exp $ */ #include "dosbox.h" #include "cross.h" @@ -197,6 +197,10 @@ void Config::PrintConfig(char const * const configfilename) const { char temp[50];char helpline[256]; FILE* outfile=fopen(configfilename,"w+t"); if(outfile==NULL) return; + + /* Print start of configfile and add an return to improve readibility. */ + fprintf(outfile,MSG_Get("CONFIGFILE_INTRO"),VERSION); + fprintf(outfile,"\n"); for (const_it tel=sectionlist.begin(); tel!=sectionlist.end(); tel++){ /* Print out the Section header */ strcpy(temp,(*tel)->GetName()); @@ -252,6 +256,14 @@ void Config::Init() { (*tel)->ExecuteInit(); } } +void Section::AddInitFunction(SectionFunction func,bool canchange) { + initfunctions.push_back(Function_wrapper(func,canchange)); +} + +void Section::AddDestroyFunction(SectionFunction func,bool canchange) { + destroyfunctions.push_front(Function_wrapper(func,canchange)); +} + void Section::ExecuteInit(bool initall) { typedef std::list::iterator func_it; diff --git a/src/misc/support.cpp b/src/misc/support.cpp index 934e048..21fd50c 100644 --- a/src/misc/support.cpp +++ b/src/misc/support.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: support.cpp,v 1.31 2007/01/08 19:45:41 qbix79 Exp $ */ +/* $Id: support.cpp,v 1.32 2007/06/12 20:22:09 c2woody Exp $ */ #include #include @@ -91,7 +91,6 @@ char * ScanCMDRemain(char * cmd) { } char * StripWord(char *&line) { - bool quoted=false; char * scan=line; scan=ltrim(scan); if (*scan=='"') { diff --git a/src/platform/visualc/config.h b/src/platform/visualc/config.h index 45cfa5b..9694796 100644 --- a/src/platform/visualc/config.h +++ b/src/platform/visualc/config.h @@ -1,10 +1,10 @@ #define INLINE __forceinline -#define VERSION "0.70" +#define VERSION "0.71" /* Define to 1 to enable internal debugger, requires libcurses */ -#define C_DEBUG 1 +#define C_DEBUG 0 /* Define to 1 to enable screenshots, requires libpng */ #define C_SSHOT 1 @@ -22,11 +22,15 @@ #define C_HEAVY_DEBUG 0 /* The type of cpu this host has */ -#define C_HOSTCPU X86 +#define C_TARGETCPU X86 +//#define C_TARGETCPU X86_64 /* Define to 1 to use x86 dynamic cpu core */ #define C_DYNAMIC_X86 1 +/* Define to 1 to use recompiling cpu core. Can not be used together with the dynamic-x86 core */ +#define C_DYNREC 0 + /* Enable memory function inlining in */ #define C_CORE_INLINE 0 diff --git a/src/shell/shell.cpp b/src/shell/shell.cpp index f41c491..d25d521 100644 --- a/src/shell/shell.cpp +++ b/src/shell/shell.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell.cpp,v 1.84 2007/02/22 08:34:10 qbix79 Exp $ */ +/* $Id: shell.cpp,v 1.86 2007/07/03 17:32:14 qbix79 Exp $ */ #include #include @@ -400,12 +400,16 @@ public: autoexec[12].Install(std::string("MOUNT C \"") + buffer + "\""); autoexec[13].Install("C:"); upcase(name); - if(strstr(name,".BAT") == 0) { - autoexec[14].Install(name); - } else { + if(strstr(name,".BAT") != 0) { /* BATch files are called else exit will not work */ autoexec[14].Install(std::string("CALL ") + name); + } else if((strstr(name,".IMG") != 0) || (strstr(name,".IMA") !=0)) { + /* Boot image files */ + autoexec[14].Install(std::string("BOOT ") + name); + } else { + autoexec[14].Install(name); } + if(addexit) autoexec[15].Install("exit"); } } @@ -420,10 +424,10 @@ void AUTOEXEC_Init(Section * sec) { test = new AUTOEXEC(sec); } -static char * path_string="PATH=Z:\\"; -static char * comspec_string="COMSPEC=Z:\\COMMAND.COM"; -static char * full_name="Z:\\COMMAND.COM"; -static char * init_line="/INIT AUTOEXEC.BAT"; +static char const * const path_string="PATH=Z:\\"; +static char const * const comspec_string="COMSPEC=Z:\\COMMAND.COM"; +static char const * const full_name="Z:\\COMMAND.COM"; +static char const * const init_line="/INIT AUTOEXEC.BAT"; void SHELL_Init() { /* Add messages */ diff --git a/src/shell/shell_batch.cpp b/src/shell/shell_batch.cpp index 289289c..2e201d2 100644 --- a/src/shell/shell_batch.cpp +++ b/src/shell/shell_batch.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_batch.cpp,v 1.23 2007/01/08 19:45:42 qbix79 Exp $ */ +/* $Id: shell_batch.cpp,v 1.24 2007/06/13 07:22:17 qbix79 Exp $ */ #include #include @@ -100,9 +100,9 @@ emptyline: /* Not a command line number has to be an environment */ char * first=strchr(cmd_read,'%'); if (!first) continue; *first++=0; - std::string temp; - if (shell->GetEnvStr(cmd_read,temp)) { - const char * equals=strchr(temp.c_str(),'='); + std::string env; + if (shell->GetEnvStr(cmd_read,env)) { + const char * equals=strchr(env.c_str(),'='); if (!equals) continue; equals++; strcpy(cmd_write,equals); @@ -120,14 +120,14 @@ emptyline: bool BatchFile::Goto(char * where) { Bit32u pos=0; - char cmd[CMD_MAXLINE]; + char cmd_buffer[CMD_MAXLINE]; char * cmd_write; DOS_SeekFile(file_handle,&pos,DOS_SEEK_SET); /* Scan till we have a match or return false */ Bit8u c;Bit16u n; again: - cmd_write=cmd; + cmd_write=cmd_buffer; do { n=1; DOS_ReadFile(file_handle,&c,&n); @@ -137,7 +137,7 @@ again: } } while (c!='\n' && n); *cmd_write++=0; - char *nospace = trim(cmd); + char *nospace = trim(cmd_buffer); if (nospace[0] == ':') { char* nonospace = trim(nospace+1); if (strcasecmp(nonospace,where)==0) return true; diff --git a/src/shell/shell_cmds.cpp b/src/shell/shell_cmds.cpp index e5199f2..d0f2cfe 100644 --- a/src/shell/shell_cmds.cpp +++ b/src/shell/shell_cmds.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* $Id: shell_cmds.cpp,v 1.73 2007/01/21 16:18:12 qbix79 Exp $ */ +/* $Id: shell_cmds.cpp,v 1.76 2007/06/14 08:23:46 qbix79 Exp $ */ #include #include @@ -62,18 +62,22 @@ static SHELL_Cmd cmd_list[]={ { "PATH", 1, &DOS_Shell::CMD_PATH, "SHELL_CMD_PATH_HELP"}, { "VER", 0, &DOS_Shell::CMD_VER, "SHELL_CMD_VER_HELP"}, {0,0,0,0} -}; -bool DOS_Shell::CheckConfig(char* cmd,char*line) { - Section* test = control->GetSectionFromProperty(cmd); +}; + +static char empty_char = 0; +static char* empty_string = &empty_char; + +bool DOS_Shell::CheckConfig(char* cmd_in,char*line) { + Section* test = control->GetSectionFromProperty(cmd_in); if(!test) return false; if(line && !line[0]) { - char const* val = test->GetPropValue(cmd); + char const* val = test->GetPropValue(cmd_in); if(val) WriteOut("%s\n",val); return true; } char newcom[1024]; newcom[0] = 0; strcpy(newcom,"z:\\config "); strcat(newcom,test->GetName()); strcat(newcom," "); - strcat(newcom,cmd);strcat(newcom,line); + strcat(newcom,cmd_in);strcat(newcom,line); DoCommand(newcom); return true; } @@ -81,8 +85,8 @@ bool DOS_Shell::CheckConfig(char* cmd,char*line) { void DOS_Shell::DoCommand(char * line) { /* First split the line into command and arguments */ line=trim(line); - char cmd[CMD_MAXLINE]; - char * cmd_write=cmd; + char cmd_buffer[CMD_MAXLINE]; + char * cmd_write=cmd_buffer; while (*line) { if (*line==32) break; if (*line=='/') break; @@ -92,7 +96,7 @@ void DOS_Shell::DoCommand(char * line) { *cmd_write=0; Bit32u cmd_index=0; while (cmd_list[cmd_index].name) { - if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) { + if (strcasecmp(cmd_list[cmd_index].name,cmd_buffer)==0) { (this->*(cmd_list[cmd_index].handler))(line); return; } @@ -102,20 +106,20 @@ void DOS_Shell::DoCommand(char * line) { *cmd_write++=*line++; } *cmd_write=0; - if (strlen(cmd)==0) return; + if (strlen(cmd_buffer)==0) return; /* Check the internal list */ Bit32u cmd_index=0; while (cmd_list[cmd_index].name) { - if (strcasecmp(cmd_list[cmd_index].name,cmd)==0) { + if (strcasecmp(cmd_list[cmd_index].name,cmd_buffer)==0) { (this->*(cmd_list[cmd_index].handler))(line); return; } cmd_index++; } /* This isn't an internal command execute it */ - if(Execute(cmd,line)) return; - if(CheckConfig(cmd,line)) return; - WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),cmd); + if(Execute(cmd_buffer,line)) return; + if(CheckConfig(cmd_buffer,line)) return; + WriteOut(MSG_Get("SHELL_EXECUTE_ILLEGAL_COMMAND"),cmd_buffer); } #define HELP(command) \ @@ -183,7 +187,7 @@ void DOS_Shell::CMD_HELP(char * args){ while (cmd_list[cmd_index].name) { if (optall || !cmd_list[cmd_index].flags) { WriteOut("<\033[34;1m%-8s\033[0m> %s",cmd_list[cmd_index].name,MSG_Get(cmd_list[cmd_index].help)); - if(!(++write_count%22)) CMD_PAUSE(""); + if(!(++write_count%22)) CMD_PAUSE(empty_string); } cmd_index++; } @@ -198,8 +202,9 @@ void DOS_Shell::CMD_RENAME(char * args){ char* slash = strrchr(arg1,'\\'); if(slash) { slash++; - //If directory specified (crystal caves installer) - // rename from c:\X : rename c:\abc.exe abc.shr. File must appear in C:\ + /* If directory specified (crystal caves installer) + * rename from c:\X : rename c:\abc.exe abc.shr. + * File must appear in C:\ */ char dir_source[DOS_PATHLENGTH]={0}; //Copy first and then modify, makes GCC happy @@ -331,7 +336,7 @@ void DOS_Shell::CMD_DIR(char * args) { } bool optW=ScanCMDBool(args,"W"); - bool optS=ScanCMDBool(args,"S"); + ScanCMDBool(args,"S"); bool optP=ScanCMDBool(args,"P"); bool optAD=ScanCMDBool(args,"AD"); char * rem=ScanCMDRemain(args); @@ -398,18 +403,18 @@ void DOS_Shell::CMD_DIR(char * args) { /* Skip non-directories if option AD is present */ if(optAD && !(attr&DOS_ATTR_DIRECTORY) ) continue; - - char * ext=""; + + char * ext = empty_string; if (!optW && (name[0] != '.')) { ext = strrchr(name, '.'); - if (!ext) ext = ""; - else *ext++ = '\0'; + if (!ext) ext = empty_string; + else *ext++ = 0; } - Bit8u day = date & 0x001f; - Bit8u month = (date >> 5) & 0x000f; - Bit16u year = (date >> 9) + 1980; - Bit8u hour = (time >> 5 ) >> 6; - Bit8u minute = (time >> 5) & 0x003f; + Bit8u day = (Bit8u)(date & 0x001f); + Bit8u month = (Bit8u)((date >> 5) & 0x000f); + Bit16u year = (Bit16u)((date >> 9) + 1980); + Bit8u hour = (Bit8u)((time >> 5 ) >> 6); + Bit8u minute = (Bit8u)((time >> 5) & 0x003f); /* output the file */ if (attr & DOS_ATTR_DIRECTORY) { @@ -435,7 +440,7 @@ void DOS_Shell::CMD_DIR(char * args) { } if(optP) { if(!(++p_count%(22*w_size))) { - CMD_PAUSE(""); + CMD_PAUSE(empty_string); } } } while ( (ret=DOS_FindNext()) ); @@ -742,6 +747,13 @@ void DOS_Shell::CMD_GOTO(char * args) { StripSpaces(args); if (!bf) return; if (*args &&(*args==':')) args++; + //label ends at the first space + char* non_space = args; + while (*non_space) { + if((*non_space == ' ') || (*non_space == '\t')) + *non_space = 0; + else non_space++; + } if (!*args) { WriteOut(MSG_Get("SHELL_CMD_GOTO_MISSING_LABEL")); return; @@ -860,7 +872,7 @@ void DOS_Shell::CMD_LOADHIGH(char *args){ HELP("LOADHIGH"); Bit16u umb_start=dos_infoblock.GetStartOfUMBChain(); Bit8u umb_flag=dos_infoblock.GetUMBChainState(); - Bit8u old_memstrat=DOS_GetMemAllocStrategy()&0xff; + Bit8u old_memstrat=(Bit8u)(DOS_GetMemAllocStrategy()&0xff); if (umb_start==0x9fff) { if ((umb_flag&1)==0) DOS_LinkUMBsToMemChain(1); DOS_SetMemAllocStrategy(0x80); // search in UMBs first @@ -955,7 +967,7 @@ void DOS_Shell::CMD_VER(char *args) { char* word = StripWord(args); if(strcasecmp(word,"set")) return; word = StripWord(args); - dos.version.major = atoi(word); - dos.version.minor = atoi(args); + dos.version.major = (Bit8u)(atoi(word)); + dos.version.minor = (Bit8u)(atoi(args)); } else WriteOut(MSG_Get("SHELL_CMD_VER_VER"),VERSION,dos.version.major,dos.version.minor); } diff --git a/visualc_net/dosbox.vcproj b/visualc_net/dosbox.vcproj index 9c7bef8..4a45482 100644 --- a/visualc_net/dosbox.vcproj +++ b/visualc_net/dosbox.vcproj @@ -167,6 +167,9 @@ + + @@ -278,6 +281,34 @@ RelativePath="..\src\cpu\core_dyn_x86\string.h"> + + + + + + + + + + + + + + + + + +