diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 3a9b3d3aa4..e0b3b33ac1 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -1117,6 +1117,8 @@ + + diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs new file mode 100644 index 0000000000..0d7e44e51e --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/LibPicoDrive.cs @@ -0,0 +1,16 @@ +using BizHawk.Common.BizInvoke; +using BizHawk.Emulation.Cores.Waterbox; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive +{ + public abstract class LibPicoDrive : LibWaterboxCore + { + [BizImport(CC)] + public abstract bool Init(); + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs new file mode 100644 index 0000000000..e5792d474e --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/PicoDrive/PicoDrive.cs @@ -0,0 +1,51 @@ +using BizHawk.Emulation.Common; +using BizHawk.Emulation.Cores.Waterbox; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BizHawk.Emulation.Cores.Consoles.Sega.PicoDrive +{ + [CoreAttributes("PicoDrive", "notaz", true, false, + "0e352905c7aa80b166933970abbcecfce96ad64e", "https://github.com/notaz/picodrive", false)] + public class PicoDrive : WaterboxCore + { + private LibPicoDrive _core; + + [CoreConstructor("GEN")] + public PicoDrive(CoreComm comm, byte[] rom) + : base(comm, new Configuration + { + MaxSamples = 2048, + DefaultWidth = 320, + DefaultHeight = 224, + MaxWidth = 320, + MaxHeight = 480, + SystemId = "GEN" + }) + { + _core = PreInit(new PeRunnerOptions + { + Filename = "picodrive.wbx", + SbrkHeapSizeKB = 4096, + SealedHeapSizeKB = 4096, + InvisibleHeapSizeKB = 4096, + MmapHeapSizeKB = 65536, + PlainHeapSizeKB = 4096, + }); + + _exe.AddReadonlyFile(rom, "romfile.md"); + if (!_core.Init()) + throw new InvalidOperationException("Core rejected the rom!"); + _exe.RemoveReadonlyFile("romfile.md"); + PostInit(); + } + + protected override LibWaterboxCore.FrameInfo FrameAdvancePrep(IController controller, bool render, bool rendersound) + { + return new LibWaterboxCore.FrameInfo(); + } + } +} diff --git a/waterbox/gpgx/.vscode/settings.json b/waterbox/gpgx/.vscode/settings.json new file mode 100644 index 0000000000..a5401e1c1f --- /dev/null +++ b/waterbox/gpgx/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "editor.tabSize": 4, + "editor.insertSpaces": false, + "editor.detectIndentation": false +} \ No newline at end of file diff --git a/waterbox/picodrive/.vscode/settings.json b/waterbox/picodrive/.vscode/settings.json new file mode 100644 index 0000000000..a5401e1c1f --- /dev/null +++ b/waterbox/picodrive/.vscode/settings.json @@ -0,0 +1,6 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "editor.tabSize": 4, + "editor.insertSpaces": false, + "editor.detectIndentation": false +} \ No newline at end of file diff --git a/waterbox/picodrive/AUTHORS b/waterbox/picodrive/AUTHORS new file mode 100644 index 0000000000..d4791101d0 --- /dev/null +++ b/waterbox/picodrive/AUTHORS @@ -0,0 +1,56 @@ +notaz +core, 32X emulation, CD code, ARM asm renderers, dynamic recompilers, +Pandora, GPH device, PSP, Gizmondo ports, CPU core hacks +lots of additional coding (see changeLog). +Homepage: http://notaz.gp2x.de/ + +fDave +project starter +Cyclone 68000 core and PicoDrive core itself + +Chui +FAME/C 68k interpreter core +(based on C68K by Stephane Dallongeville) + +Stephane Dallongeville (written), NJ (optimized) +CZ80 Z80 interpreter core + +Reesy & FluBBa +DrZ80, the Z80 interpreter written in ARM assembly. +Homepage: http://reesy.gp32x.de/ (defunct) + +Tatsuyuki Satoh, Jarek Burczynski, MAME development +software implementation of Yamaha FM sound generator + +MAME development +Texas Instruments SN76489 / SN76496 programmable tone/noise generator +Homepage: http://www.mame.net/ + +Eke-Eke +CD graphics processor and CD controller implementation (from Genesis Plus GX) + + +Additional thanks +----------------- + +* Charles MacDonald (http://cgfm2.emuviews.com/) for old but still very useful + info about genesis hardware. +* Steve Snake for all that he has done for Genesis emulation scene. +* Stephane Dallongeville for writing Gens and making it open source. +* Tasco Deluxe for his reverse engineering work on SVP and some mappers. +* Bart Trzynadlowski for his SSFII and 68000 docs. +* Haze for his research (http://mamedev.emulab.it/haze/). +* Lordus, Exophase and Rokas for various ideas. +* Nemesis for his YM2612, VDP research and docs. +* Eke-Eke for sharing the knowledge and his work on Genesis Plus GX. +* Many posters at spritesmind.net forums for valuable information. +* Mark and Jean-loup for zlib library. +* ketchupgun for the skin. +* GP2X specific help: rlyeh, Squidge, Dzz, A_SN, Alex and GP32X posters. +* Gizmondo code: Kingcdr, Reesy, jens.l (for the device itself) +* Hardware: craigix (GP2X), EvilDragon (Wiz, Caanoo, Pandora, ...) + and jens.l (Gizmondo) +* Paul Cercueil for OpenDingux port. +* Inder for some graphics. +* squarepusher for some libretro fixes +* Anyone else I forgot. Let me know if it's you. diff --git a/waterbox/picodrive/COPYING b/waterbox/picodrive/COPYING new file mode 100644 index 0000000000..c0f5a3ca83 --- /dev/null +++ b/waterbox/picodrive/COPYING @@ -0,0 +1,30 @@ + + Redistribution and use of this code or any derivative works are permitted + provided that the following conditions are met: + + * Redistributions may not be sold, nor may they be used in a commercial + product or activity. + + * Redistributions that are modified from the original source must include the + complete source code, including the source code for all components used by a + binary built from the modified sources. However, as a special exception, the + source code distributed need not include anything that is normally distributed + (in either source or binary form) with the major components (compiler, kernel, + and so on) of the operating system on which the executable runs, unless that + component itself accompanies the executable. + + * Redistributions must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/waterbox/picodrive/ChangeLog b/waterbox/picodrive/ChangeLog new file mode 100644 index 0000000000..a8ba44eb50 --- /dev/null +++ b/waterbox/picodrive/ChangeLog @@ -0,0 +1,487 @@ +1.91 (2013-10-12) + + Added OpenDingux support (Paul Cercueil). + * Save directory changed to ~/.picodrive/ for generic platform build + (Paul Cercueil). + + Revived GP2X/Caanoo/Wiz support. + + Switched to cleaner CD controller code from Eke-Eke's Genesis Plus GX. + * Fixed overflow issue where cd emulation would break after + ~10 minutes of gameplay. + * Fixed synchronization issue where model1 CD BIOS would randomly hang. + +1.90 (2013-09-24) + + 32X+CD emulation has been implemented. + + CD graphics processor code has been replaced with much cleaner Eke-Eke's + implementation from Genesis Plus GX. + + CD PCM code has been completely rewritten. + * Various CD compatibility issues have been solved. Hopefully no more + regressions this time. + * pandora: fixed tv-out (again), added automatic layer switching + * libretro: fixed crackling sound for some games, added some core options + * sdl: multiple joystick support has been fixed (Victor Luchits) + +1.85 (2013-08-31) + * Lots of 32X compatibility and accuracy improvements. All commercial games + are booting now, but some still have issues. + * Fixed some regressions in MegaCD code, like hang in jap BIOS. + * Implemented pause for SMS. + * Updated UI with improvements from PCSX ReARMed. + * Frontend timing has been rewritten, should no longer slowly desync from + LCD on pandora. + * Added libretro and SDL 32/64bit ports, fixed compatibility issues with + Android, iOS. + * Various other things I forgot (it has been a while since last release..) + +1.80 (2010-09-19) + + Added Caanoo support. Now the GP2X binary supports GP2X F100/F200, Wiz + and Caanoo. Lots of internal refactoring to support this. + + Enabled 32X and SMS code. It's still unfinished but better release something + now than wait even more (it has been in development for more then a year now + due to various other projects or simply lack of time). + + Pandora: added hardware scaler support, including ability to resize the + layer and control filtering. + + GP2X: Added basic line-doubling vertical scaling option. + * Changed the way keys are bound, no need to unbind old one any more. + * Handle MP3s with ID3 tags better (some MP3s with ID3 did not play). + * Improved shadow/hilight color levels. + * Fixed broken cheat support. + +1.80beta2 + * Pandora: updated documentation. + +1.80beta1 (2010-06-02) + + Added pandora port. + * Internal refactoring for 32x/SMS support. + * Move mapper database to external file. + + Added preliminary SMS emulation. + + Added emulation of 32x peripherals including VDP. More work is needed here. + + ARM: Added new SH2 recompiler for 32x. Some unification with SVP one. + - Disabled most of the above bacause I'm not yet happy with the results. + +1.56 (2009-09-19) + * Changed sync in Sega CD emulation again. Should fix games that + broke after changes in 1.51a. + * Fixed default keys rebinding when they shouldn't. + * Fixed sram being loaded from wrong game. + * Emu should no longer hang shortly after using fast-forward. + * Fixed save states sometimes no longer showing up in save state menu. + * ARM: some asm code refactoring for slight speed improvement. + +1.55 + + Added Wiz support. Now the same GP2X binary supports F100/F200 and Wiz. + * Changed shadow/hilight handling a bit, fixes some effects in Pirates! Gold. + * Complete input code rewrite. This fixes some limitations like not allowing + to control both players using single input device. It also allows to use + more devices (like keyboards) on Linux based devices. + * Options menu has been reordered, "restore defaults" option added. + +1.51b + * Fixed a crash when uncompressed savestate is loaded. + * Fixed an idle loop detection related hanging problem. + * PSP: fixed another palette related regression. + * UIQ3: updated frontend for the latest emu core. + +1.51a + * Fixed a sync problem between main and sub 68k. Should fix the hanging + problem for some games. + * ARM: fixed a crash when CD savestate is loaded just after loading ROM. + +1.51 + * Improved bin_to_cso_mp3 tool, it should no longer complain about + missing lame.exe even if it's in working dir. + * Fixed a regression from 1.50, which caused slowdowns in Final Fight. + * Fixed some regressions from 1.50 related to sprite limit and palette + handling (caused graphical glitches in some games). + + Added ABC turbo actions to key config. + * Some other minor adjustments. + +1.50 + + Added some basic support for Sega Pico, a MegaDrive-based toy. + + Added proper support for cue/bin images, including cdda playback. + .cue sheets with iso/cso/mp3/wav files listed in them are now + supported too (but 44kHz restriction still applies). + + Added bin_to_cso_mp3 tool, based on Exophase's bin_to_iso_ogg. + The tool can convert .cue/.bin Sega CD images to .cso/.mp3. + * Greatly improved Sega CD load times. + * Changed how scheduling between 68k and z80 is handled. Improves + performance for some games. Credits to Lordus for the idea. + * YM2612 state was not 100% saved, this should be better now. + * Improved renderer performance for shadow/hilight mode. + * Added a hack for YM2612 frequency overflow issue (bleep noises + in Shaq Fu, Spider-Man - The Animated Series (intro music), etc.) + Credits to Nemesis @ spritesmind forum. Works only if sound rate + is set to 44kHz. + + Implemented some sprite rendering improvements, as suggested by + Exophase. Games with lots of sprites now perform better. + + Added better idle loop detection, based on Lordus' idea again. + - "accurate timing" option removed, as disabling it no longer + improves performance. + - "accurate sprites" was removed too, the new sprite code can + properly handle sprite priorities in all cases. + * Timers adjusted again. + * Improved .smd detection code. + * ARM: fixed a bug in DrZ80 core, which could cause problems in + some rare cases. + * ARM: fixed a problem of occasional clicks on MP3 music start. + * Minor general optimizations and menu improvements. + * Fixed a bug in Sega CD savestate loader, where the game would + sometimes crash after load. + * Fixed a crash of games using eeprom (introduced in 1.40b). + * PSP: fixed suspend/resume (hopefully for real). + +1.40c + * Fixed a problem with sound in Marble Madness. + * GP2X: Fixed minor problem with key config. + +1.40b + * Fixed sprite masking code. Thanks to Lordus for explaining how it works. + + Added "disable sprite limit" option. + + PSP: added black level adjustment to display options. + * Changed reset to act as 'soft' reset. + + Added detection for Puggsy (it doesn't really have sram). + * Some small timing adjustments. + +1.40a + * GP2X: Fixed a binding problem with up and down keys. + * Default game config no longer overrides global user config. + +1.40 + + Added support for SVP (Sega Virtua Processor) to emulate Virtua Racing, + wrote ARM recompiler and some HLE code for VR. Credits to Exophase and + Rokas for various ideas. + * Changed config file format, files are now human-readable. Game specific + configs are now held in single file (but old game config files are still + read when new one is missing). + * Fixed a bug where some key combos didn't work as expected. + * Fixed a regression in renderer (ARM ports only, some graphic glitches in + rare cases). + * Adjusted fast renderer to work with more games, including VR. + * Fixed a problem where SegaCD RAM cart data was getting lost on reset. + * GP2X: Greatly reduced SegaCD FMV game slowdowns by disabling read-ahead + in the Linux kernel and C library (thanks to Rokas and Exophase for ideas + again). Be sure to keep "ReadAhead buffer" OFF to avoid slowdowns. + + PicoDrive now comes with a game config file for some games which need + special settings, so they should now work out-of-the-box. More games will + be added with later updates. + + GP2X: Files now can be deleted by pressing A+SELECT in the file browser. + +1.35b + * PSP: mp3 code should no longer fail on 1.5 firmware. + + PSP: added gamma adjustment option. + + Added .cso ISO format support. Useful for non-FMV games. + * It is now possile to force a region after the ROM is loaded. + * Fixed a sram bug in memhandlers (fixes Shining in the Darkness saves). + * PSP: fixed another bug in memhanlers, which crashed the emu for some games + (like NBA Jam and NHL 9x). + + PSP: added suspend/resume handling for Sega CD games. + + GP2X: added additional low volume levels for my late-night gaming sessions + (in stereo mode only). + + GP2X: added "fast forward" action in key config. Not recommended to use for + Sega CD, may case problems there. + * Some other small tweaks I forgot about. + +1.35a + * PSP: fixed a bug which prevented to load any ROMs after testing the BIOS. + * PSP: fixed incorrect CZ80 memory map setup, which caused Z80 crashes and + graphics corruption in EU Mega CD model1 BIOS menus. + + PSP: added additional "set to 4:3 scaled" display option for convenience. + + PSP: Added an option to disable frame limitter (works only with non-auto frameskip). + +1.35 + + PSP port added. Lots of new code for it. Integrated modified FAME/C, CZ80 cores. + + Some minor generic optimizations. + * Patched some code which was crashing under PSP, but was working in GP2X/Giz + (although it should have crashed there too). + * Readme updated. + +1.34 + + Gizmondo port added. + + Some new optimizations in memory handlers, and for shadow/hilight mode. + + Added some hacks to make more games work without enabling "accurate timing". + * Adjusted timing for "accurate timing" mode and added preliminary VDP FIFO + emulation. Fixes Double Dragon 2, tearing in Chaos Engine and some other games. + * Fixed a few games not having sound at startup. + * Updated serial EEPROM code to support more games. Thanks to EkeEke for + providing info about additional EEPROM types and game mappers. + * The above change fixed hang of NBA Jam. + * Minor adjustments to control configurator. + +1.33 + * Updated Cyclone core to 0.0088. + + Added A r k's usbjoy fix. + + Added "perfect vsync" option, which adjusts GP2X LCD refresh rate and syncs + emulation to it to eliminate tearing and ensure smoothest scrolling possible. + + Added an option to use A_SN's gamma curve for gamma correction (improves dark + and bright color display for mk2s). + * Sometimes stray sounds were played after loading a savestate. Fixed. + * Fixed a problem where >6MB mp3s were corrupted in memory (sound glitches in + Snatcher). + * PD no longer overwrites video player code in memory, video player now can be + used after exiting PicoDrive. + * Fixed a bug which was causing Sonic 3 code to deadlock in some rare conditions + if "accurate timing" was not enabled. + * Fixed support for large hacked ROMs like "Ultimate Mortal Kombat Trilogy". + Upto 10MB hacked ROMs are supported now. + + Config profiles added (press left/right when saving config). + * Changed key configuration behavior to the one from gpfce (should be more + intuitive). + + Added some skinning capabilities to the menu system with default skin by + ketchupgun. Delete skin directory if you want old behaviour. + * Some other little tweaks I forgot about. + +1.32 + + Added some new scaling options. + + Added ability to reload CD images while game is running (needed for games + with multiple CDs, like Night Trap). + + Added RAM cart emulation. + * Fixed DMA timing emulation (caused lock-ups for some genesis games). + * Idle loop detection was picking up wrong code and causing glitches, fixed. + * The ym2612 code on 940 now can handle multiple updates per frame + (fixes Thunger Force III "seiren" level drums for example). + * Memory handlers were ignoring some writes to PSG chip, fixed (missing sounds in + Popful Mail, Silpheed). + * Improved z80 timing, should fix some sound problems. + * Fixed a bug with sram register (fixes Phantasy Star 4). + * ROM loader was incorrectly identifying some ROMs as invalid. Fixed. + * Added code for PRG ram write protection register (Dungeon Explorer). + * The memory mode register change in 1.31 was unsafe and caused some glitches in + AH-3 Thunderstrike. Fixed. + * Fixed a file descriptor leak. + * Updated documentation, added Gmenu2x manual. + +1.31 + * Changed the way memory mode register is read (fixes Lunar 2, broken in 1.30). + * Fixed TAS opcode on sub-68k side (fixes Batman games). + * File browser now filters out mp3s, saves and some other files, which are not ROMS. + +1.30 + + ISO files now can be zipped. Note that this causes VERY long loading times. + + Added data pre-buffering support, this allows to reduce frequency of short pauses + in FMV games (caused by SD access), but makes those pauses longer. + * Fixed PCM DMA transfers (intro FMV in Popful Mail). + + Properly implemented "decode" data transformation (Jaguar XJ220). + * Integrated "better sync" code into cyclone code, what made this mode much faster. + * Fixed a bug related to game specific config saving. + * Frameskipper was skipping sound processing, what caused some audio desyncs. Fixed. + * Fixed reset not working for some games. + + New assembly optimized memory handlers for CD (gives at least a few fps). + Also re-enabled all optimizations from 0.964 release. + + New idle-loop detection code for sub-68k. Speeds up at least a few games. + +1.201 + + Added basic cheat support (GameGenie and Genecyst patches). + +1.20 + * Fixed a long-standing problem in audio mixing code which caused slight distortions + at lower sample rates. + * Changed the way 920 and 940 communicates (again), should be more reliable and give + slight performance increase. + * Some optimizations in audio mixing code. + * Some menu changes (background added, smaller font in ROM browser, savestate loader + now can select slots). + + 1M mode DMA transfers implemented (used by FMV games like Night Trap and Sewer Shark). + + Games now can run code from WORD RAM in 1M mode (fixes Adventures of Willy Beamish). + + "Cell arrange" address mapping is now emulated (Heart of the alien). + + "Color numeric operation" is now emulated (text in Lunar 2, Silpheed intro graphics). + + "Better sync" option added (prevents some games from hanging). + +1.14 + + Region autodetection now can be customized. + * When CDDA music tracks changed, old buffer contents were incorrectly played. Fixed. + * BRAM is now automatically formatted (no need to enter BIOS menu and format any more). + * Games now can be reset, CDDA music no longer breaks after loading another ISO. + * Fixed a race condition between 920 and 940 which sometimes caused CDDA music not to play. + + Savestates implemented for Sega/Mega CD. + + PCM sound added. + * Some mixer code rewritten in asm. 22kHz and 11kHz sound rates are now supported in + Mega CD mode (but mp3s must still be 44kHz stereo). + + Timer emulation added. + * CDC DMA tansfers fixed. Snatcher and probably some more games now boot. + * 2M word RAM -> VDP transfers fixed, no more corruption in Ecco and some other games. + +1.10 + + GP2X: Added experimental Sega CD support. + + GP2X: Added partial gmv movie playback support. + +0.964 (2006-12-03) + * GP2X: Fixed a sound buffer underflow issue on lower sample rate modes, which was + happening for NTSC games and causing sound clicks. + * GP2X: Redone key config to better support USB joysticks (now multiple joysticks + should be useable and configurable). + + GP2X: Added save confirmation option. + + GP2X: Added 940 CPU crash detection. + + ALL: UIQ3 port added. + +0.963 + * GP2X: Gamma-reset-on-entering-menu bug fixed. + * GP2X: Recompiled PicoDrive with gcc profiling option set as described here: + http://www.gp32x.com/board/index.php?showtopic=28490 + +0.962 + * GP2X: Fixed an issue with incorrect sounds in some games when dualcore operation + was enabled (for example punch sound in SOR). + * GP2X: Limited max volume to 90, because higher values often cause distortions. + * GP2X: Fixed a bug with lower res scaling. + * GP2X: Gamma is now reset on exit. + +0.96 + * ALL: Severely optimized MAME's YM2612 core, part of it is now rewritten in asm. + + GP2X: The YM2612's code now can be run in GP2X's ARM940T CPU, what causes large + performance increase. + * ALL: Accurate renderers are slightly faster now. + + GP2X: Using quadruple buffering instead of doublebuffer now, also updated + framelimitter, this should eliminate some scrolling and tearing problems. + * GP2X: Fixed some flickering issues of 8bit accurate renderer. + + GP2X: craigix's RAM timings now can be enabled in the menu (see advanced options). + + GP2X: Added ability to save config for specific games only. + + GP2X: Gamma control added (using GP2X's hardware capabilities for this). + * GP2X: Volume keys are now configurable. + + GP2X: GnoStiC added USB joystick support, I made it possible to use it for + player 2 control (currently untested). + * GP2X: squidgehack is now applied through kernel module (cleaner way). + +0.95 + * ALL: Fixed a bug in sprite renderer which was causing slowdowns for some games. + + GP2X: Added command line support + + GP2X: Added optional hardware scaling for lower-res games like Shining Force. + * ALL: Sound chips are now sampled 2 times per frame. This fixed some games which + had missing sounds (Vectorman 2 1st level, Thunder Force 3 water level, + etc.). + + ALL: Added another accurate 8-bit renderer which is slightly faster and made it + default. + +0.945 + + GP2X: Added frame limiter for frameskipped modes. + * GP2X: Increased brightness a bit (unused pixel bits now also contain data). + * GP2X: Suidgehack was not applied correctly (was applied before allocating some + high memory and had no effect). + +0.94 + + Added GP2X port. + * Improved interrupt timing, Mazin Saga and Burning Force now works. + * Rewritten renderer code to better suit GP2X, should be faster on other + ports too. + + Added support for banking used by 12-in-1 and 4-in-1 ROMs (thanks Haze). + + Added some protection device faking, used by some unlicensed games like + Super Bubble Bobble, King of Fighters, Elf Wor, ... (thanks to Haze again) + + Added primitive Virtua Racing SVP faking, so menus can be seen now. + +0.93 + * Fixed a problem with P900/P910 key configuration in FC mode. + * Improved shadow/hilight mode emulation. Still not perfect, but should be + enough for most games. + + Save state slots added. + + Region selector added. + +0.92 + VDP changes: + * VDP emulation is now more accurate (fixes flickering in Chase HQ II, + Super Hang-On and some other problems in other games). + * HV counter emulation is now much more accurate. Fixes the Asterix games, + line in Road Rash 3, etc. + * Minor sprite and layer scroll masking bugs fixed. + + Added partial interlace mode renderer (Sonic 2 vs mode) + * Fixed a crash in both renderers when certain size window layers were used. + + Added emulation of shadow/hilight operator sprites. Other shadow/hilight + effects are still unemulated. + + Sprite emulation is more accurate, sprite limit is emulated. + + Added "accurate sprites" option, which always draws sprites in correct + order and emulates sprite collision bit, but is significantly slower. + + Emulation changes: + * Improved interrupt handling, added deferred interrupt emulation + (Lemmings, etc). + + Added serial EEPROM SRAM support (Wonder Boy in Monster World, + Megaman - The Wily Wars and many EA sports games like NBA Jam). + + Implemented ROM banking for Super Street Fighter II - The New Challengers + * Updated to the latest version of DrZ80 core, integrated memory handlers + in it for better performance. A noticeable performance increase, but save + states may not work from the previous version (you can only use them with + sound disabled in that case). + + SRAM word read handler was using incorrect byte order, fixed. + + Changes in Cyclone 0.0086: + + Added missing CHK opcode handler (used by SeaQuest DSV). + + Added missing TAS opcode handler (Gargoyles,Bubba N Stix,...). As in real genesis, + memory write-back phase is ignored (but can be enabled in config.h if needed). + + Added missing NBCD and TRAPV opcode handlers. + + Added missing addressing mode for CMP/EOR. + + Added some minor optimizations. + - Removed 216 handlers for 2927 opcodes which were generated for invalid addressing modes. + + Fixed flags for ASL, NEG, NEGX, DIVU, ADDX, SUBX, ROXR. + + Bugs fixed in MOVEP, LINK, ADDQ, DIVS handlers. + * Undocumented flags for CHK, ABCD, SBCD and NBCD are now emulated the same way as in Musashi. + + Added Uninitialized Interrupt emulation. + + Altered timing for about half of opcodes to match Musashi's. + +0.80 + * Nearly all VDP code was rewritten in ARM asm. Gives ~10-25% performance + increase (depends on game). + * Optimized 32-column renderer not to render tiles offscreen, games which + use 32-column display (like Shining Force) run ~50% faster. + + Added new "Alternative renderer", which gives another ~30-45% performance + increase (in addition to mentioned above), but works only with some games, + because it is missing some features (it uses tile-based rendering + instead of default line-based and disables H-ints). + + Added "fit2" display mode for all FC gamers. It always uses 208x146 for + P800 and 208x208 for all other phones. + + Added volume control for Motorolas (experimental). + + VDP changes: + + Added support for vertical window (used by Vapor Trail, Mercs, GRIND + Stormer and others). + + Added sprite masking (hiding), adds some speed. + + Added preliminary H counter emulation. Comix Zone and Sonic 3D Blast + special stage are now playable. + + Added column based vertical scrolling (Gunstar Heroes battleship level, + Sonic and Knuckles lava boss, etc). + + Emulation changes: + + Re-added and improved Z80 faking when Z80 is disabled. Many games now can + be played without enabling Z80 (Lost Vikings, Syndicate, etc), but some + still need it (International Superstar Soccer Deluxe). + * Improved ym2612 timers, Outrun music plays at correct speed, voices in + Earthworm Jim play better, more games play sound. + * I/O registers now remember their values (needed for Pirates! Gold) + + Added support for 6 button pad. + + Changes in Cyclone 0.0083wip: + + Added missing CHK opcode (used by SeaQuest DSV). + + Added missing TAS opcode (Gargoyles). As in real genesis, write-back phase + is ignored (but is enabled for other systems). + + Backported stuff from Snes9x: + * Fixed Pxxx jog up/down which were not working in game. + + Added an option to gzip save states to save space. + + The emulator now pauses whenever it is loosing focus, so it will now pause + when alarm/ponecall/battery low/... windows come up. + - Removed 'pause on phonecall' feature, as it is no longer needed. + + Video fix for asian A1000s. + +0.70 + * Started using tools from "Symbian GCC Improvement Project", which give + considerable speed increase (~4fps in "center 90" mode). + * Rewrote some drawing routines in ARM assembly (gives ~6 more fps in + "center 90" mode). + * Minor improvement to 0 and 180 "fit" modes. Now they look slightly better + and are faster. + * Minor stability improvements (emulator is less likely to crash). + + Added some background for OSD text for better readability. + + Added Pal/NTSC detection. This is needed for proper sound speed. + + Implemented Reesy's DrZ80 Z80 emu. Made some changes to it with hope to make + it faster. + + Implemented ym2612 emu from the MAME project. Runs well but sometimes sounds + a bit weird. Could be a little faster, so made some changes too. + + Implemented SN76489 emu from the MAME project. + + Added two separate sound output methods (mediaserver and cmaudiofb) with + autodetection (needs testing). + * Fixed VDP DMA fill emulation (as described in Charles MacDonald's docs), + fixes Contra and some other games. + +0.301 + Launcher: + * Launcher now starts emulation process from current directory, + not from hardcoded paths. + * Improved 'pause on call' feature, should hopefully work with Motorola phones. + +0.30 (2006-01-07) + Initial release based on fDave's code. diff --git a/waterbox/picodrive/Makefile b/waterbox/picodrive/Makefile new file mode 100644 index 0000000000..313ccb3961 --- /dev/null +++ b/waterbox/picodrive/Makefile @@ -0,0 +1,43 @@ +CC = x86_64-nt64-midipix-gcc + +CCFLAGS:=-I. \ + -I../emulibc \ + -Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \ + -std=c99 -fomit-frame-pointer -fvisibility=hidden \ + -falign-functions=16 \ + -DLSB_FIRST -DNDEBUG -DEMU_F68K -D_USE_CZ80 \ + -O0 -g + +TARGET = picodrive.wbx + +LDFLAGS = -Wl,--dynamicbase,--export-all-symbols + +ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) +SRCS:=$(shell find $(ROOT_DIR) -type f -name '*.c') +OBJ_DIR:=$(ROOT_DIR)/obj + +_OBJS:=$(SRCS:.c=.o) +OBJS:=$(patsubst $(ROOT_DIR)%,$(OBJ_DIR)%,$(_OBJS)) + +$(OBJ_DIR)/%.o: %.c + @mkdir -p $(@D) + @$(CC) -c -o $@ $< $(CCFLAGS) + +all: $(TARGET) + +.PHONY: clean all + +$(TARGET).in: $(OBJS) + @$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so + +$(TARGET): $(TARGET).in +# strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104 + cp $< $@ + +clean: + rm -rf $(OBJ_DIR) + rm -f $(TARGET).in + rm -f $(TARGET) + +#install: +# $(CP) $(TARGET) $(DEST_$(ARCH)) diff --git a/waterbox/picodrive/Makefile.libretro b/waterbox/picodrive/Makefile.libretro new file mode 100644 index 0000000000..96e4fe91e4 --- /dev/null +++ b/waterbox/picodrive/Makefile.libretro @@ -0,0 +1,154 @@ +# Makefile for PicoDrive (libretro) + +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +endif +endif + +CC ?= gcc +CXX ?= g++ +AS ?= as +CC_AS ?= $(CC) +CFLAGS ?= + +TARGET_NAME := picodrive + +asm_memory = 0 +asm_render = 0 +asm_ym2612 = 0 +asm_misc = 0 +asm_cdpico = 0 +asm_cdmemory = 0 +asm_mix = 0 + +ifeq ($(platform), unix) + TARGET := $(TARGET_NAME)_libretro.so + SHARED := -shared +else ifeq ($(platform), osx) + TARGET := $(TARGET_NAME)_libretro.dylib + SHARED := -dynamiclib +else ifeq ($(platform), ios) + TARGET := $(TARGET_NAME)_libretro_ios.dylib + SHARED := -dynamiclib + + CC = clang -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 + CXX = clang++ -arch armv7 -isysroot $(IOSSDK) -miphoneos-version-min=5.0 + CC_AS = perl ./tools/gas-preprocessor.pl $(CC) -miphoneos-version-min=5.0 + CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon -marm + ASFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfpu=neon + CFLAGS += -DIOS -miphoneos-version-min=5.0 + + ARCH := arm + + use_cyclone = 0 + use_fame = 1 + use_drz80 = 0 + use_cz80 = 1 + use_sh2drc = 1 + use_svpdrc = 1 + +else ifeq ($(platform), ps3) + TARGET := $(TARGET_NAME)_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe + AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), sncps3) + TARGET := $(TARGET_NAME)_libretro_ps3.a + CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe + AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), psl1ght) + TARGET := $(TARGET_NAME)_libretro_psl1ght.a + CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) + AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) + CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), psp1) + TARGET := $(TARGET_NAME)_libretro_psp1.a + CC = psp-gcc$(EXE_EXT) + AR = psp-ar$(EXE_EXT) + CFLAGS += -DPSP -G0 +else ifeq ($(platform), xenon) + TARGET := $(TARGET_NAME)_libretro_xenon360.a + CC = xenon-gcc$(EXE_EXT) + AR = xenon-ar$(EXE_EXT) + CFLAGS += -D__LIBXENON__ -m32 -D__ppc__ +else ifeq ($(platform), ngc) + TARGET := $(TARGET_NAME)_libretro_ngc.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), wii) + TARGET := libretro_$(TARGET_NAME)_wii.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DBLARGG_BIG_ENDIAN=1 -D__ppc__ +else ifeq ($(platform), qnx) + TARGET := $(TARGET_NAME)_libretro_qnx.so + CC = qcc -Vgcc_ntoarmv7le + CC_AS = $(CC) + CFLAGS += -DBASE_ADDR_FIXED=0 -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp + ASFLAGS += -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp + + ARCH = arm + ARM_ASM = 1 +else ifneq (,$(findstring armv,$(platform))) + TARGET := $(TARGET_NAME)_libretro.so + SHARED := -shared -Wl,--no-undefined +ifneq (,$(findstring cortexa8,$(platform))) + CFLAGS += -marm -mcpu=cortex-a8 + ASFLAGS += -mcpu=cortex-a8 +else ifneq (,$(findstring cortexa9,$(platform))) + CFLAGS += -marm -mcpu=cortex-a9 + ASFLAGS += -mcpu=cortex-a9 +endif + CFLAGS += -marm +ifneq (,$(findstring neon,$(platform))) + CFLAGS += -mfpu=neon + ASFLAGS += -mfpu=neon +endif +ifneq (,$(findstring softfloat,$(platform))) + CFLAGS += -mfloat-abi=softfp + ASFLAGS += -mfloat-abi=softfp +else ifneq (,$(findstring hardfloat,$(platform))) + CFLAGS += -mfloat-abi=hard + ASFLAGS += -mfloat-abi=hard +endif +ifneq (,$(findstring armasm,$(platform))) + ARM_ASM = 1 +endif + ARCH = arm +else + TARGET := $(TARGET_NAME)_libretro.dll + CC = gcc + LD_FLAGS := -fPIC + SHARED := -shared -static-libgcc -static-libstdc++ + CFLAGS += -D__WIN32__ -D__WIN32_LIBRETRO__ +endif + +ifeq ($(ARM_ASM),1) +asm_memory = 1 +asm_render = 1 +asm_ym2612 = 1 +asm_misc = 1 +asm_cdpico = 1 +asm_cdmemory = 1 +asm_mix = 1 +endif + +CFLAGS += -fPIC +LDLIBS += -lm +SHARED ?= -shared +LDFLAGS += $(SHARED) + +PLATFORM = libretro +NO_CONFIG_MAK = yes + +include Makefile diff --git a/waterbox/picodrive/Makefile.old b/waterbox/picodrive/Makefile.old new file mode 100644 index 0000000000..30b246fdc0 --- /dev/null +++ b/waterbox/picodrive/Makefile.old @@ -0,0 +1,227 @@ +TARGET ?= PicoDrive +CFLAGS += -Wall -ggdb -falign-functions=2 +CFLAGS += -I. +ifndef DEBUG +CFLAGS += -O3 -DNDEBUG -ffunction-sections +ifeq ($(findstring clang,$(CC)),) +LDFLAGS += -Wl,--gc-sections +endif +endif +#CFLAGS += -DEVT_LOG +#CFLAGS += -DDRC_CMP +#cpu_cmp = 1 +#drc_debug = 7 +#profile = 1 + + +all: config.mak target_ + +ifndef NO_CONFIG_MAK +ifneq ($(wildcard config.mak),) +config.mak: ./configure + @echo $@ is out-of-date, running configure + @sed -n "/.*Configured with/s/[^:]*: //p" $@ | sh +include config.mak +else +config.mak: + @echo "Please run ./configure before running make!" + @exit 1 +endif +else # NO_CONFIG_MAK +config.mak: +endif + +# default settings +ifeq "$(ARCH)" "arm" +use_cyclone ?= 1 +use_drz80 ?= 1 +use_sh2drc ?= 1 +use_svpdrc ?= 1 + +asm_memory ?= 1 +asm_render ?= 1 +asm_ym2612 ?= 1 +asm_misc ?= 1 +asm_cdpico ?= 1 +asm_cdmemory ?= 1 +asm_mix ?= 1 +else # if not arm +use_fame ?= 1 +use_cz80 ?= 1 +endif + +-include Makefile.local + +ifneq "$(use_cyclone)" "1" +# due to CPU stop flag access +asm_cdpico = 0 +asm_cdmemory = 0 +endif + +ifeq "$(PLATFORM)" "opendingux" +opk: $(TARGET).opk + +$(TARGET).opk: $(TARGET) + $(RM) -rf .opk_data + cp -r platform/opendingux/data .opk_data + cp $< .opk_data/PicoDrive + $(STRIP) .opk_data/PicoDrive + mksquashfs .opk_data $@ -all-root -noappend -no-exports -no-xattrs + +OBJS += platform/opendingux/inputmap.o + +# OpenDingux is a generic platform, really. +PLATFORM := generic +endif +ifeq ("$(PLATFORM)",$(filter "$(PLATFORM)","rpi1" "rpi2")) +CFLAGS += -DHAVE_GLES -DRASPBERRY +CFLAGS += -I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads/ -I/opt/vc/include/interface/vmcs_host/linux/ +LDFLAGS += -ldl -lbcm_host -L/opt/vc/lib -lEGL -lGLESv2 +OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME +OBJS += platform/common/plat_sdl.o +OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o +OBJS += platform/libpicofe/plat_dummy.o +OBJS += platform/libpicofe/gl.o +OBJS += platform/libpicofe/gl_platform.o +USE_FRONTEND = 1 +endif +ifeq "$(PLATFORM)" "generic" +OBJS += platform/linux/emu.o platform/linux/blit.o # FIXME +OBJS += platform/common/plat_sdl.o +OBJS += platform/libpicofe/plat_sdl.o platform/libpicofe/in_sdl.o +OBJS += platform/libpicofe/plat_dummy.o +USE_FRONTEND = 1 +endif +ifeq "$(PLATFORM)" "pandora" +platform/common/menu_pico.o: CFLAGS += -DPANDORA +platform/libpicofe/linux/plat.o: CFLAGS += -DPANDORA +OBJS += platform/pandora/plat.o +OBJS += platform/pandora/asm_utils.o +OBJS += platform/common/arm_utils.o +OBJS += platform/libpicofe/linux/fbdev.o +OBJS += platform/libpicofe/linux/xenv.o +OBJS += platform/libpicofe/pandora/plat.o +USE_FRONTEND = 1 +endif +ifeq "$(PLATFORM)" "gp2x" +OBJS += platform/common/arm_utils.o +OBJS += platform/libpicofe/gp2x/in_gp2x.o +OBJS += platform/libpicofe/gp2x/soc.o +OBJS += platform/libpicofe/gp2x/soc_mmsp2.o +OBJS += platform/libpicofe/gp2x/soc_pollux.o +OBJS += platform/libpicofe/gp2x/plat.o +OBJS += platform/libpicofe/gp2x/pollux_set.o +OBJS += platform/gp2x/940ctl.o +OBJS += platform/gp2x/plat.o +OBJS += platform/gp2x/emu.o +OBJS += platform/gp2x/vid_mmsp2.o +OBJS += platform/gp2x/vid_pollux.o +OBJS += platform/gp2x/warm.o +USE_FRONTEND = 1 +PLATFORM_MP3 = 1 +endif +ifeq "$(PLATFORM)" "libretro" +OBJS += platform/libretro.o +endif + +ifeq "$(USE_FRONTEND)" "1" + +# common +OBJS += platform/common/main.o platform/common/emu.o \ + platform/common/menu_pico.o platform/common/config_file.o + +# libpicofe +OBJS += platform/libpicofe/input.o platform/libpicofe/readpng.o \ + platform/libpicofe/fonts.o platform/libpicofe/linux/in_evdev.o \ + platform/libpicofe/linux/plat.o + +# libpicofe - sound +OBJS += platform/libpicofe/sndout.o +ifneq ($(findstring oss,$(SOUND_DRIVERS)),) +platform/libpicofe/sndout.o: CFLAGS += -DHAVE_OSS +OBJS += platform/libpicofe/linux/sndout_oss.o +endif +ifneq ($(findstring alsa,$(SOUND_DRIVERS)),) +platform/libpicofe/sndout.o: CFLAGS += -DHAVE_ALSA +OBJS += platform/libpicofe/linux/sndout_alsa.o +endif +ifneq ($(findstring sdl,$(SOUND_DRIVERS)),) +platform/libpicofe/sndout.o: CFLAGS += -DHAVE_SDL +OBJS += platform/libpicofe/sndout_sdl.o +endif + +ifeq "$(ARCH)" "arm" +OBJS += platform/libpicofe/arm_linux.o +endif + +endif # USE_FRONTEND + +OBJS += platform/common/mp3.o +ifeq "$(PLATFORM_MP3)" "1" +else ifeq "$(HAVE_LIBAVCODEC)" "1" +OBJS += platform/common/mp3_libavcodec.o +else +OBJS += platform/common/mp3_dummy.o +endif + +ifeq "$(PLATFORM)" "libretro" +# zlib +OBJS += zlib/gzio.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o zlib/trees.o \ + zlib/deflate.o zlib/crc32.o zlib/adler32.o zlib/zutil.o zlib/compress.o zlib/uncompr.o +CFLAGS += -Izlib +endif +# unzip +OBJS += unzip/unzip.o + + +include platform/common/common.mak + +OBJS += $(OBJS_COMMON) +CFLAGS += $(addprefix -D,$(DEFINES)) + +ifneq ($(findstring gcc,$(CC)),) +LDFLAGS += -Wl,-Map=$(TARGET).map +endif + + +target_: $(TARGET) + +clean: + $(RM) $(TARGET) $(OBJS) + $(RM) -r .opk_data + +$(TARGET): $(OBJS) + $(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS) $(LDLIBS) + +pprof: platform/linux/pprof.c + $(CC) -O2 -ggdb -DPPROF -DPPROF_TOOL -I../../ -I. $^ -o $@ + +tools/textfilter: tools/textfilter.c + make -C tools/ textfilter + +.s.o: + $(CC) $(CFLAGS) -c $< -o $@ + +# special flags - perhaps fix this someday instead? +pico/draw.o: CFLAGS += -fno-strict-aliasing +pico/draw2.o: CFLAGS += -fno-strict-aliasing +pico/mode4.o: CFLAGS += -fno-strict-aliasing +pico/cd/memory.o: CFLAGS += -fno-strict-aliasing +pico/cd/cd_file.o: CFLAGS += -fno-strict-aliasing +pico/cd/pcm.o: CFLAGS += -fno-strict-aliasing +pico/cd/LC89510.o: CFLAGS += -fno-strict-aliasing +pico/cd/gfx_cd.o: CFLAGS += -fno-strict-aliasing + +# fame needs ~2GB of RAM to compile on gcc 4.8 +# on x86, this is reduced by ~300MB when debug info is off (but not on ARM) +# not using O3 and -fno-expensive-optimizations seems to also help, but you may +# want to remove this stuff for better performance if your compiler can handle it +cpu/fame/famec.o: CFLAGS += -g0 -O2 -fno-expensive-optimizations + +# random deps +pico/carthw/svp/compiler.o : cpu/drc/emit_$(ARCH).c +cpu/sh2/compiler.o : cpu/drc/emit_$(ARCH).c +cpu/sh2/mame/sh2pico.o : cpu/sh2/mame/sh2.c +pico/pico.o pico/cd/mcd.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h +pico/memory.o pico/cd/memory.o pico/32x/memory.o : pico/pico_int.h pico/memory.h +cpu/fame/famec.o: cpu/fame/famec.c cpu/fame/famec_opcodes.h diff --git a/waterbox/picodrive/README b/waterbox/picodrive/README new file mode 100644 index 0000000000..d9c10910cf --- /dev/null +++ b/waterbox/picodrive/README @@ -0,0 +1,21 @@ + +This is yet another Megadrive / Genesis / Sega CD / Mega CD / 32X / SMS +emulator, which was written having ARM-based handheld devices in mind +(such as smartphones and handheld consoles like GP2X and Pandora), +but also runs on non-ARM little-endian hardware too. + +The emulator is heavily optimized for ARM, features assembly cores for +68k, Z80 and VDP chip emulation, also has dynamic recompilers for SH2 and +SSP16 (for 32X and SVP emulation). It was started by Dave (aka fdave, +finalburn author) as basic Genesis/Megadrive emulator for Pocket PC, +then taken over and expanded by notaz. + +PicoDrive was the first emulator ever to properly emulate Virtua Racing and +it's SVP chip. + +How to compile on Raspbian Wheezy: + +export CC=gcc-4.8 +export CXX=g++-4.8 +./configure --platform=rpi2 +make diff --git a/waterbox/picodrive/bizhawk.c b/waterbox/picodrive/bizhawk.c new file mode 100644 index 0000000000..5d5b848e60 --- /dev/null +++ b/waterbox/picodrive/bizhawk.c @@ -0,0 +1,153 @@ +#include +#include +#include + +#include "../emulibc/emulibc.h" +#include "../emulibc/waterboxcore.h" +#include "pico/pico.h" +#include "pico/cd/cue.h" + +void lprintf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +int PicoCartResize(int newsize) +{ + // TODO: change boards that use this to store their extra data elsewhere + return -1; +} + +int PicoCdCheck(const char *fname_in, int *pregion) +{ + return CIT_NOT_CD; +} + +cue_data_t *cue_parse(const char *fname) +{ + return NULL; +} + +pm_file *pm_open(const char *path) +{ + FILE *f = fopen(path, "rb"); + if (!f) + return NULL; + fseek(f, 0, SEEK_END); + pm_file *ret = calloc(1, sizeof(*ret)); + ret->file = f; + ret->size = ftell(f); + fseek(f, 0, SEEK_SET); + ret->type = PMT_UNCOMPRESSED; + return ret; +} +size_t pm_read(void *ptr, size_t bytes, pm_file *stream) +{ + return fread(ptr, 1, bytes, (FILE *)stream->file); +} +int pm_seek(pm_file *stream, long offset, int whence) +{ + return fseek((FILE *)stream->file, offset, whence); +} +int pm_close(pm_file *fp) +{ + int ret = fclose((FILE *)fp->file); + fp->file = NULL; + free(fp); + return ret; +} + +static int video_start_line; +static int video_line_count; +static int video_width; +static uint16_t* video_buffer; + +void emu_video_mode_change(int start_line, int line_count, int is_32cols) +{ + video_start_line = start_line; + video_line_count = line_count; + video_width = is_32cols ? 256 : 320; +} + +// "switch to 16bpp mode?" +void emu_32x_startup(void) +{ +} + +int mp3_get_bitrate(void *f, int size) { return 0; } +void mp3_start_play(void *f, int pos) {} +void mp3_update(int *buffer, int length, int stereo) {} + +ECL_EXPORT int Init(void) +{ + video_buffer = alloc_invisible(512 * 512 * sizeof(uint16_t)); + + PicoInit(); + PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN); + PicoSetInputDevice(1, PICO_INPUT_PAD_6BTN); + PicoDrawSetOutBuf(video_buffer, 512 * sizeof(uint16_t)); + + if (PicoLoadMedia("romfile.md", NULL, NULL, NULL, PM_MD_CART) != PM_MD_CART) + return 0; + PicoDrawSetOutFormat(PDF_RGB555, 0); // TODO: what is "use_32x_line_mode"? + PicoPower(); + + return 1; +} + +typedef struct +{ + FrameInfo b; +} MyFrameInfo; + +static void Blit(const uint16_t *src, FrameInfo *f) +{ + f->Width = video_width; + f->Height = video_line_count; + uint8_t *dst = (uint8_t *)f->VideoBuffer; + src += 512 * video_start_line; + if (video_width == 256) + src += 32; + + for (int j = 0; j < video_line_count; j++) + { + for (int i = 0; i < video_width; i++) + { + uint16_t c = src[i]; + *dst++ = c << 3 & 0xf8 | c >> 2 & 7; + *dst++ = c >> 3 & 0xfa | c >> 9 & 3; + *dst++ = c >> 8 & 0xf8 | c >> 13 & 7; + *dst++ = 0xff; + } + src += 512; + } +} + +ECL_EXPORT void FrameAdvance(MyFrameInfo *f) +{ + PicoLoopPrepare(); + PicoFrame(); + Blit(video_buffer, &f->b); + f->b.Samples = 735; // TODO +} + +static uint8_t dumbo[16]; +ECL_EXPORT void GetMemoryAreas(MemoryArea *m) +{ + m[0].Data = dumbo; + m[0].Name = "TODO"; + m[0].Size = 16; + m[0].Flags = MEMORYAREA_FLAGS_WRITABLE | MEMORYAREA_FLAGS_WORDSIZE1 | MEMORYAREA_FLAGS_PRIMARY; +} + +ECL_EXPORT void SetInputCallback(void (*callback)(void)) +{ +} + +int main(void) +{ + return 0; +} diff --git a/waterbox/picodrive/cpu/cz80/cz80.c b/waterbox/picodrive/cpu/cz80/cz80.c new file mode 100644 index 0000000000..d83307b79c --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80.c @@ -0,0 +1,488 @@ +/****************************************************************************** + * + * CZ80 (Z80 CPU emulator) version 0.9 + * Compiled with Dev-C++ + * Copyright 2004-2005 St�phane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#include +#include +#include +#include "cz80.h" + +#if PICODRIVE_HACKS +#include +#endif + +#ifndef ALIGN_DATA +#ifdef _MSC_VER +#define ALIGN_DATA +#define inline +#undef CZ80_USE_JUMPTABLE +#define CZ80_USE_JUMPTABLE 0 +#else +#define ALIGN_DATA __attribute__((aligned(4))) +#endif +#endif + +#define CF 0x01 +#define NF 0x02 +#define PF 0x04 +#define VF PF +#define XF 0x08 +#define HF 0x10 +#define YF 0x20 +#define ZF 0x40 +#define SF 0x80 + + +/****************************************************************************** + �}�N�� +******************************************************************************/ + +#include "cz80macro.h" + + +/****************************************************************************** + �O���[�o���\���� +******************************************************************************/ + +cz80_struc ALIGN_DATA CZ80; + + +/****************************************************************************** + ���[�J���ϐ� +******************************************************************************/ + +static UINT8 ALIGN_DATA cz80_bad_address[1 << CZ80_FETCH_SFT]; + +static UINT8 ALIGN_DATA SZ[256]; +static UINT8 ALIGN_DATA SZP[256]; +static UINT8 ALIGN_DATA SZ_BIT[256]; +static UINT8 ALIGN_DATA SZHV_inc[256]; +static UINT8 ALIGN_DATA SZHV_dec[256]; +#if CZ80_BIG_FLAGS_ARRAY +static UINT8 ALIGN_DATA SZHVC_add[2*256*256]; +static UINT8 ALIGN_DATA SZHVC_sub[2*256*256]; +#endif + + +/****************************************************************************** + ���[�J���֐� +******************************************************************************/ + +/*-------------------------------------------------------- + ���荞�݃R�[���o�b�N +--------------------------------------------------------*/ + +static INT32 Cz80_Interrupt_Callback(INT32 line) +{ + return 0xff; +} + + +/****************************************************************************** + CZ80�C���^�t�F�[�X�֐� +******************************************************************************/ + +/*-------------------------------------------------------- + CPU������ +--------------------------------------------------------*/ + +void Cz80_Init(cz80_struc *CPU) +{ + UINT32 i, j, p; +#if CZ80_BIG_FLAGS_ARRAY + int oldval, newval, val; + UINT8 *padd, *padc, *psub, *psbc; +#endif + + memset(CPU, 0, sizeof(cz80_struc)); + + memset(cz80_bad_address, 0xff, sizeof(cz80_bad_address)); + + for (i = 0; i < CZ80_FETCH_BANK; i++) + { + CPU->Fetch[i] = (FPTR)cz80_bad_address; +#if CZ80_ENCRYPTED_ROM + CPU->OPFetch[i] = 0; +#endif + } + + // flags tables initialisation + for (i = 0; i < 256; i++) + { + SZ[i] = i & (SF | YF | XF); + if (!i) SZ[i] |= ZF; + + SZ_BIT[i] = i & (SF | YF | XF); + if (!i) SZ_BIT[i] |= ZF | PF; + + for (j = 0, p = 0; j < 8; j++) if (i & (1 << j)) p++; + SZP[i] = SZ[i]; + if (!(p & 1)) SZP[i] |= PF; + + SZHV_inc[i] = SZ[i]; + if(i == 0x80) SZHV_inc[i] |= VF; + if((i & 0x0f) == 0x00) SZHV_inc[i] |= HF; + + SZHV_dec[i] = SZ[i] | NF; + if (i == 0x7f) SZHV_dec[i] |= VF; + if ((i & 0x0f) == 0x0f) SZHV_dec[i] |= HF; + } + +#if CZ80_BIG_FLAGS_ARRAY + padd = &SZHVC_add[ 0*256]; + padc = &SZHVC_add[256*256]; + psub = &SZHVC_sub[ 0*256]; + psbc = &SZHVC_sub[256*256]; + + for (oldval = 0; oldval < 256; oldval++) + { + for (newval = 0; newval < 256; newval++) + { + /* add or adc w/o carry set */ + val = newval - oldval; + *padd = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padd |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) < (oldval & 0x0f)) *padd |= HF; + if (newval < oldval ) *padd |= CF; + if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padd |= VF; + padd++; + + /* adc with carry set */ + val = newval - oldval - 1; + *padc = (newval) ? ((newval & 0x80) ? SF : 0) : ZF; + *padc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) <= (oldval & 0x0f)) *padc |= HF; + if (newval <= oldval) *padc |= CF; + if ((val ^ oldval ^ 0x80) & (val ^ newval) & 0x80) *padc |= VF; + padc++; + + /* cp, sub or sbc w/o carry set */ + val = oldval - newval; + *psub = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psub |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) > (oldval & 0x0f)) *psub |= HF; + if (newval > oldval) *psub |= CF; + if ((val^oldval) & (oldval^newval) & 0x80) *psub |= VF; + psub++; + + /* sbc with carry set */ + val = oldval - newval - 1; + *psbc = NF | ((newval) ? ((newval & 0x80) ? SF : 0) : ZF); + *psbc |= (newval & (YF | XF)); /* undocumented flag bits 5+3 */ + if ((newval & 0x0f) >= (oldval & 0x0f)) *psbc |= HF; + if (newval >= oldval) *psbc |= CF; + if ((val ^ oldval) & (oldval^newval) & 0x80) *psbc |= VF; + psbc++; + } + } +#endif + + CPU->pzR8[0] = &zB; + CPU->pzR8[1] = &zC; + CPU->pzR8[2] = &zD; + CPU->pzR8[3] = &zE; + CPU->pzR8[4] = &zH; + CPU->pzR8[5] = &zL; + CPU->pzR8[6] = &zF; // �����̓s����AA�Ɠ���ւ� + CPU->pzR8[7] = &zA; // �����̓s����AF�Ɠ���ւ� + + CPU->pzR16[0] = pzBC; + CPU->pzR16[1] = pzDE; + CPU->pzR16[2] = pzHL; + CPU->pzR16[3] = pzAF; + + zIX = zIY = 0xffff; + zF = ZF; + + CPU->Interrupt_Callback = Cz80_Interrupt_Callback; +} + + +/*-------------------------------------------------------- + CPU���Z�b�g +--------------------------------------------------------*/ + +void Cz80_Reset(cz80_struc *CPU) +{ + memset(CPU, 0, (FPTR)&CPU->BasePC - (FPTR)CPU); + Cz80_Set_Reg(CPU, CZ80_PC, 0); +} + +/* */ +#if PICODRIVE_HACKS +static inline unsigned char picodrive_read(unsigned short a) +{ + uptr v = z80_read_map[a >> Z80_MEM_SHIFT]; + if (map_flag_set(v)) + return ((z80_read_f *)(v << 1))(a); + return *(unsigned char *)((v << 1) + a); +} +#endif + +/*-------------------------------------------------------- + CPU���s +--------------------------------------------------------*/ + +INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles) +{ +#if CZ80_USE_JUMPTABLE +#include "cz80jmp.inc" +#endif + + FPTR PC; +#if CZ80_ENCRYPTED_ROM + FPTR OPBase; +#endif + UINT32 Opcode; + UINT32 adr = 0; + UINT32 res; + UINT32 val; + int afterEI = 0; + union16 *data; + + PC = CPU->PC; +#if CZ80_ENCRYPTED_ROM + OPBase = CPU->OPBase; +#endif + CPU->ICount = cycles - CPU->ExtraCycles; + CPU->ExtraCycles = 0; + + if (!CPU->HaltState) + { +Cz80_Exec: + if (CPU->ICount > 0) + { +Cz80_Exec_nocheck: + data = pzHL; + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_op.inc" + } + + if (afterEI) + { + afterEI = 0; +Cz80_Check_Interrupt: + if (CPU->IRQState != CLEAR_LINE) + { + CHECK_INT + CPU->ICount -= CPU->ExtraCycles; + CPU->ExtraCycles = 0; + } + goto Cz80_Exec; + } + } + else CPU->ICount = 0; + +Cz80_Exec_End: + CPU->PC = PC; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = OPBase; +#endif + cycles -= CPU->ICount; +#if !CZ80_EMULATE_R_EXACTLY + zR = (zR + (cycles >> 2)) & 0x7f; +#endif + + return cycles; +} + + +/*-------------------------------------------------------- + ���荞�ݏ��� +--------------------------------------------------------*/ + +void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state) +{ + if (line == IRQ_LINE_NMI) + { + zIFF1 = 0; + CPU->ExtraCycles += 11; + CPU->HaltState = 0; + PUSH_16(CPU->PC - CPU->BasePC) + Cz80_Set_Reg(CPU, CZ80_PC, 0x66); + } + else + { + CPU->IRQState = state; + + if (state != CLEAR_LINE) + { + FPTR PC = CPU->PC; +#if CZ80_ENCRYPTED_ROM + FPTR OPBase = CPU->OPBase; +#endif + + CPU->IRQLine = line; + CHECK_INT + CPU->PC = PC; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = OPBase; +#endif + } + } +} + + +/*-------------------------------------------------------- + ���W�X�^�擾 +--------------------------------------------------------*/ + +UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum) +{ + switch (regnum) + { + case CZ80_PC: return (CPU->PC - CPU->BasePC); + case CZ80_SP: return zSP; + case CZ80_AF: return zAF; + case CZ80_BC: return zBC; + case CZ80_DE: return zDE; + case CZ80_HL: return zHL; + case CZ80_IX: return zIX; + case CZ80_IY: return zIY; + case CZ80_AF2: return zAF2; + case CZ80_BC2: return zBC2; + case CZ80_DE2: return zDE2; + case CZ80_HL2: return zHL2; + case CZ80_R: return zR; + case CZ80_I: return zI; + case CZ80_IM: return zIM; + case CZ80_IFF1: return zIFF1; + case CZ80_IFF2: return zIFF2; + case CZ80_HALT: return CPU->HaltState; + case CZ80_IRQ: return CPU->IRQState; + default: return 0; + } +} + + +/*-------------------------------------------------------- + ���W�X�^�ݒ� +--------------------------------------------------------*/ + +void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val) +{ + switch (regnum) + { + case CZ80_PC: + CPU->BasePC = CPU->Fetch[val >> CZ80_FETCH_SFT]; +#if CZ80_ENCRYPTED_ROM + CPU->OPBase = CPU->OPFetch[val >> CZ80_FETCH_SFT]; +#endif + CPU->PC = val + CPU->BasePC; + break; + + case CZ80_SP: zSP = val; break; + case CZ80_AF: zAF = val; break; + case CZ80_BC: zBC = val; break; + case CZ80_DE: zDE = val; break; + case CZ80_HL: zHL = val; break; + case CZ80_IX: zIX = val; break; + case CZ80_IY: zIY = val; break; + case CZ80_AF2: zAF2 = val; break; + case CZ80_BC2: zBC2 = val; break; + case CZ80_DE2: zDE2 = val; break; + case CZ80_HL2: zHL2 = val; break; + case CZ80_R: zR = val; break; + case CZ80_I: zI = val; break; + case CZ80_IM: zIM = val; break; + case CZ80_IFF1: zIFF1 = val ? (1 << 2) : 0; break; + case CZ80_IFF2: zIFF2 = val ? (1 << 2) : 0; break; + case CZ80_HALT: CPU->HaltState = val; break; + case CZ80_IRQ: CPU->IRQState = val; break; + default: break; + } +} + + +/*-------------------------------------------------------- + �t�F�b�`�A�h���X�ݒ� +--------------------------------------------------------*/ + +void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, FPTR fetch_adr) +{ + int i, j; + + i = low_adr >> CZ80_FETCH_SFT; + j = high_adr >> CZ80_FETCH_SFT; + fetch_adr -= i << CZ80_FETCH_SFT; + + while (i <= j) + { + CPU->Fetch[i] = fetch_adr; +#if CZ80_ENCRYPTED_ROM + CPU->OPFetch[i] = 0; +#endif + i++; + } +} + + +/*-------------------------------------------------------- + �t�F�b�`�A�h���X�ݒ� (�Í���ROM�Ή�) +--------------------------------------------------------*/ + +#if CZ80_ENCRYPTED_ROM +void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom) +{ + int i, j; + + i = low_adr >> CZ80_FETCH_SFT; + j = high_adr >> CZ80_FETCH_SFT; + decrypted_rom -= i << CZ80_FETCH_SFT; + + while (i <= j) + { + CPU->OPFetch[i] = (INT32)decrypted_rom - (INT32)CPU->Fetch[i]; + i++; + } +} +#endif + + +/*-------------------------------------------------------- + ���������[�h/���C�g�֐��ݒ� +--------------------------------------------------------*/ + +void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address)) +{ + CPU->Read_Byte = Func; +} + +void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data)) +{ + CPU->Write_Byte = Func; +} + + +/*-------------------------------------------------------- + �|�[�g���[�h/���C�g�֐��ݒ� +--------------------------------------------------------*/ + +void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port)) +{ + CPU->IN_Port = Func; +} + +void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value)) +{ + CPU->OUT_Port = Func; +} + + +/*-------------------------------------------------------- + �R�[���o�b�N�֐��ݒ� +--------------------------------------------------------*/ + +void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline)) +{ + CPU->Interrupt_Callback = Func; +} diff --git a/waterbox/picodrive/cpu/cz80/cz80.h b/waterbox/picodrive/cpu/cz80/cz80.h new file mode 100644 index 0000000000..9b97d3b43d --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80.h @@ -0,0 +1,309 @@ +/****************************************************************************** + * + * CZ80 (Z80 CPU emulator) version 0.9 + * Compiled with Dev-C++ + * Copyright 2004-2005 Stphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#ifndef CZ80_H +#define CZ80_H + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************/ +/* Compiler dependant defines */ +/******************************/ + +#ifndef UINT8 +#define UINT8 unsigned char +#endif + +#ifndef INT8 +#define INT8 signed char +#endif + +#ifndef UINT16 +#define UINT16 unsigned short +#endif + +#ifndef INT16 +#define INT16 signed short +#endif + +#ifndef UINT32 +#define UINT32 unsigned int +#endif + +#ifndef INT32 +#define INT32 signed int +#endif + +#ifndef FPTR +#define FPTR unsigned long +#endif + +/*************************************/ +/* Z80 core Structures & definitions */ +/*************************************/ + +#define CZ80_FETCH_BITS 4 // [4-12] default = 8 + +#define CZ80_FETCH_SFT (16 - CZ80_FETCH_BITS) +#define CZ80_FETCH_BANK (1 << CZ80_FETCH_BITS) + +#define PICODRIVE_HACKS 1 +#define CZ80_LITTLE_ENDIAN 1 +#define CZ80_USE_JUMPTABLE 1 +#define CZ80_BIG_FLAGS_ARRAY 1 +//#ifdef BUILD_CPS1PSP +//#define CZ80_ENCRYPTED_ROM 1 +//#else +#define CZ80_ENCRYPTED_ROM 0 +//#endif +#define CZ80_EMULATE_R_EXACTLY 1 + +#define zR8(A) (*CPU->pzR8[A]) +#define zR16(A) (CPU->pzR16[A]->W) + +#define pzAF &(CPU->AF) +#define zAF CPU->AF.W +#define zlAF CPU->AF.B.L +#define zhAF CPU->AF.B.H +#define zA zhAF +#define zF zlAF + +#define pzBC &(CPU->BC) +#define zBC CPU->BC.W +#define zlBC CPU->BC.B.L +#define zhBC CPU->BC.B.H +#define zB zhBC +#define zC zlBC + +#define pzDE &(CPU->DE) +#define zDE CPU->DE.W +#define zlDE CPU->DE.B.L +#define zhDE CPU->DE.B.H +#define zD zhDE +#define zE zlDE + +#define pzHL &(CPU->HL) +#define zHL CPU->HL.W +#define zlHL CPU->HL.B.L +#define zhHL CPU->HL.B.H +#define zH zhHL +#define zL zlHL + +#define zAF2 CPU->AF2.W +#define zlAF2 CPU->AF2.B.L +#define zhAF2 CPU->AF2.B.H +#define zA2 zhAF2 +#define zF2 zlAF2 + +#define zBC2 CPU->BC2.W +#define zDE2 CPU->DE2.W +#define zHL2 CPU->HL2.W + +#define pzIX &(CPU->IX) +#define zIX CPU->IX.W +#define zlIX CPU->IX.B.L +#define zhIX CPU->IX.B.H + +#define pzIY &(CPU->IY) +#define zIY CPU->IY.W +#define zlIY CPU->IY.B.L +#define zhIY CPU->IY.B.H + +#define pzSP &(CPU->SP) +#define zSP CPU->SP.W +#define zlSP CPU->SP.B.L +#define zhSP CPU->SP.B.H + +#define zRealPC (PC - CPU->BasePC) +#define zPC PC + +#define zI CPU->I +#define zIM CPU->IM + +#define zwR CPU->R.W +#define zR1 CPU->R.B.L +#define zR2 CPU->R.B.H +#define zR zR1 + +#define zIFF CPU->IFF.W +#define zIFF1 CPU->IFF.B.L +#define zIFF2 CPU->IFF.B.H + +#define CZ80_SF_SFT 7 +#define CZ80_ZF_SFT 6 +#define CZ80_YF_SFT 5 +#define CZ80_HF_SFT 4 +#define CZ80_XF_SFT 3 +#define CZ80_PF_SFT 2 +#define CZ80_VF_SFT 2 +#define CZ80_NF_SFT 1 +#define CZ80_CF_SFT 0 + +#define CZ80_SF (1 << CZ80_SF_SFT) +#define CZ80_ZF (1 << CZ80_ZF_SFT) +#define CZ80_YF (1 << CZ80_YF_SFT) +#define CZ80_HF (1 << CZ80_HF_SFT) +#define CZ80_XF (1 << CZ80_XF_SFT) +#define CZ80_PF (1 << CZ80_PF_SFT) +#define CZ80_VF (1 << CZ80_VF_SFT) +#define CZ80_NF (1 << CZ80_NF_SFT) +#define CZ80_CF (1 << CZ80_CF_SFT) + +#define CZ80_IFF_SFT CZ80_PF_SFT +#define CZ80_IFF CZ80_PF + +#ifndef IRQ_LINE_STATE +#define IRQ_LINE_STATE +#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */ +#define ASSERT_LINE 1 /* assert an interrupt immediately */ +#define HOLD_LINE 2 /* hold interrupt line until acknowledged */ +#define PULSE_LINE 3 /* pulse interrupt line for one instruction */ +#define IRQ_LINE_NMI 127 /* IRQ line for NMIs */ +#endif + +enum +{ + CZ80_PC = 1, + CZ80_SP, + CZ80_AF, + CZ80_BC, + CZ80_DE, + CZ80_HL, + CZ80_IX, + CZ80_IY, + CZ80_AF2, + CZ80_BC2, + CZ80_DE2, + CZ80_HL2, + CZ80_R, + CZ80_I, + CZ80_IM, + CZ80_IFF1, + CZ80_IFF2, + CZ80_HALT, + CZ80_IRQ +}; + +typedef union +{ + struct + { +#if CZ80_LITTLE_ENDIAN + UINT8 L; + UINT8 H; +#else + UINT8 H; + UINT8 L; +#endif + } B; + UINT16 W; +} union16; + +typedef struct cz80_t +{ + union + { + UINT8 r8[8]; + union16 r16[4]; + struct + { + union16 BC; + union16 DE; + union16 HL; + union16 AF; + }; + }; + + union16 IX; + union16 IY; + union16 SP; + UINT32 unusedPC; /* left for binary compat */ + + union16 BC2; + union16 DE2; + union16 HL2; + union16 AF2; + + union16 R; + union16 IFF; + + UINT8 I; + UINT8 IM; + UINT8 HaltState; + UINT8 dummy; + + INT32 IRQLine; + INT32 IRQState; + INT32 ICount; + INT32 ExtraCycles; + + FPTR BasePC; + FPTR PC; + FPTR Fetch[CZ80_FETCH_BANK]; +#if CZ80_ENCRYPTED_ROM + FPTR OPBase; + FPTR OPFetch[CZ80_FETCH_BANK]; +#endif + + UINT8 *pzR8[8]; + union16 *pzR16[4]; + + UINT8 (*Read_Byte)(UINT32 address); + void (*Write_Byte)(UINT32 address, UINT8 data); + + UINT8 (*IN_Port)(UINT16 port); + void (*OUT_Port)(UINT16 port, UINT8 value); + + INT32 (*Interrupt_Callback)(INT32 irqline); + +} cz80_struc; + + +/*************************/ +/* Publics Z80 variables */ +/*************************/ + +extern cz80_struc CZ80; + +/*************************/ +/* Publics Z80 functions */ +/*************************/ + +void Cz80_Init(cz80_struc *CPU); + +void Cz80_Reset(cz80_struc *CPU); + +INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles); + +void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state); + +UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum); +void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 value); + +void Cz80_Set_Fetch(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, FPTR fetch_adr); +#if CZ80_ENCRYPTED_ROM +void Cz80_Set_Encrypt_Range(cz80_struc *CPU, UINT32 low_adr, UINT32 high_adr, UINT32 decrypted_rom); +#endif + +void Cz80_Set_ReadB(cz80_struc *CPU, UINT8 (*Func)(UINT32 address)); +void Cz80_Set_WriteB(cz80_struc *CPU, void (*Func)(UINT32 address, UINT8 data)); + +void Cz80_Set_INPort(cz80_struc *CPU, UINT8 (*Func)(UINT16 port)); +void Cz80_Set_OUTPort(cz80_struc *CPU, void (*Func)(UINT16 port, UINT8 value)); + +void Cz80_Set_IRQ_Callback(cz80_struc *CPU, INT32 (*Func)(INT32 irqline)); + +#ifdef __cplusplus +}; +#endif + +#endif /* CZ80_H */ diff --git a/waterbox/picodrive/cpu/cz80/cz80_op.inc b/waterbox/picodrive/cpu/cz80/cz80_op.inc new file mode 100644 index 0000000000..3b26316d86 --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80_op.inc @@ -0,0 +1,1143 @@ +/****************************************************************************** + * + * CZ80 opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 St�phane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTable[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + NOP +-----------------------------------------*/ + + OP(0x00): // NOP + +/*----------------------------------------- + LD r8 (same register) +-----------------------------------------*/ + + OP(0x40): // LD B,B + OP(0x49): // LD C,C + OP(0x52): // LD D,D + OP(0x5b): // LD E,E + OP(0x64): // LD H,H + OP(0x6d): // LD L,L + OP(0x7f): // LD A,A + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OP(0x41): // LD B,C + OP(0x42): // LD B,D + OP(0x43): // LD B,E + OP(0x44): // LD B,H + OP(0x45): // LD B,L + OP(0x47): // LD B,A + + OP(0x48): // LD C,B + OP(0x4a): // LD C,D + OP(0x4b): // LD C,E + OP(0x4c): // LD C,H + OP(0x4d): // LD C,L + OP(0x4f): // LD C,A + + OP(0x50): // LD D,B + OP(0x51): // LD D,C + OP(0x53): // LD D,E + OP(0x54): // LD D,H + OP(0x55): // LD D,L + OP(0x57): // LD D,A + + OP(0x58): // LD E,B + OP(0x59): // LD E,C + OP(0x5a): // LD E,D + OP(0x5c): // LD E,H + OP(0x5d): // LD E,L + OP(0x5f): // LD E,A + + OP(0x60): // LD H,B + OP(0x61): // LD H,C + OP(0x62): // LD H,D + OP(0x63): // LD H,E + OP(0x65): // LD H,L + OP(0x67): // LD H,A + + OP(0x68): // LD L,B + OP(0x69): // LD L,C + OP(0x6a): // LD L,D + OP(0x6b): // LD L,E + OP(0x6c): // LD L,H + OP(0x6f): // LD L,A + + OP(0x78): // LD A,B + OP(0x79): // LD A,C + OP(0x7a): // LD A,D + OP(0x7b): // LD A,E + OP(0x7c): // LD A,H + OP(0x7d): // LD A,L +OP_LD_R_R: + zR8((Opcode >> 3) & 7) = zR8(Opcode & 7); + RET(4) + + OP(0x06): // LD B,#imm + OP(0x0e): // LD C,#imm + OP(0x16): // LD D,#imm + OP(0x1e): // LD E,#imm + OP(0x26): // LD H,#imm + OP(0x2e): // LD L,#imm + OP(0x3e): // LD A,#imm +OP_LD_R_imm: + zR8(Opcode >> 3) = READ_ARG(); + RET(7) + + OP(0x46): // LD B,(HL) + OP(0x4e): // LD C,(HL) + OP(0x56): // LD D,(HL) + OP(0x5e): // LD E,(HL) + OP(0x66): // LD H,(HL) + OP(0x6e): // LD L,(HL) + OP(0x7e): // LD A,(HL) + zR8((Opcode >> 3) & 7) = READ_MEM8(zHL); + RET(7) + + OP(0x70): // LD (HL),B + OP(0x71): // LD (HL),C + OP(0x72): // LD (HL),D + OP(0x73): // LD (HL),E + OP(0x74): // LD (HL),H + OP(0x75): // LD (HL),L + OP(0x77): // LD (HL),A + WRITE_MEM8(zHL, zR8(Opcode & 7)); + RET(7) + + OP(0x36): // LD (HL), #imm + WRITE_MEM8(zHL, READ_ARG()); + RET(10) + + OP(0x0a): // LD A,(BC) +OP_LOAD_A_mBC: + adr = zBC; + goto OP_LOAD_A_mxx; + + OP(0x1a): // LD A,(DE) +OP_LOAD_A_mDE: + adr = zDE; + +OP_LOAD_A_mxx: + zA = READ_MEM8(adr); + RET(7) + + OP(0x3a): // LD A,(nn) +OP_LOAD_A_mNN: + adr = READ_ARG16(); + zA = READ_MEM8(adr); + RET(13) + + OP(0x02): // LD (BC),A +OP_LOAD_mBC_A: + adr = zBC; + goto OP_LOAD_mxx_A; + + OP(0x12): // LD (DE),A +OP_LOAD_mDE_A: + adr = zDE; + +OP_LOAD_mxx_A: + WRITE_MEM8(adr, zA); + RET(7) + + OP(0x32): // LD (nn),A +OP_LOAD_mNN_A: + adr = READ_ARG16(); + WRITE_MEM8(adr, zA); + RET(13) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OP(0x01): // LD BC,nn + OP(0x11): // LD DE,nn + OP(0x21): // LD HL,nn +OP_LOAD_RR_imm16: + zR16(Opcode >> 4) = READ_ARG16(); + RET(10) + + OP(0x31): // LD SP,nn +OP_LOAD_SP_imm16: + zSP = READ_ARG16(); + RET(10) + + OP(0xf9): // LD SP,HL +OP_LD_SP_xx: + zSP = data->W; + RET(6) + + OP(0x2a): // LD HL,(nn) +OP_LD_xx_mNN: + adr = READ_ARG16(); + data->W = READ_MEM16(adr); + RET(16) + + OP(0x22): // LD (nn),HL +OP_LD_mNN_xx: + adr = READ_ARG16(); + WRITE_MEM16(adr, data->W); + RET(16) + +/*----------------------------------------- + POP +-----------------------------------------*/ + + OP(0xc1): // POP BC + OP(0xd1): // POP DE + OP(0xf1): // POP AF +OP_POP_RR: + data = CPU->pzR16[(Opcode >> 4) & 3]; + + OP(0xe1): // POP HL +OP_POP: + POP_16(data->W) + RET(10) + +/*----------------------------------------- + PUSH +-----------------------------------------*/ + + OP(0xc5): // PUSH BC + OP(0xd5): // PUSH DE + OP(0xf5): // PUSH AF +OP_PUSH_RR: + data = CPU->pzR16[(Opcode >> 4) & 3]; + + OP(0xe5): // PUSH HL +OP_PUSH: + PUSH_16(data->W); + RET(11) + +/*----------------------------------------- + EX +-----------------------------------------*/ + + OP(0x08): // EX AF,AF' +OP_EX_AF_AF2: + res = zAF; + zAF = zAF2; + zAF2 = res; + RET(4) + + OP(0xeb): // EX DE,HL +OP_EX_DE_HL: + res = zDE; + zDE = zHL; + zHL = res; + RET(4) + + OP(0xd9): // EXX +OP_EXX: + res = zBC; + zBC = zBC2; + zBC2 = res; + res = zDE; + zDE = zDE2; + zDE2 = res; + res = zHL; + zHL = zHL2; + zHL2 = res; + RET(4) + + OP(0xe3): // EX HL,(SP) +OP_EX_xx_mSP: + adr = zSP; + res = data->W; + data->W = READ_MEM16(adr); + WRITE_MEM16(adr, res); + RET(19) + +/*----------------------------------------- + INC r8 +-----------------------------------------*/ + + OP(0x04): // INC B + OP(0x0c): // INC C + OP(0x14): // INC D + OP(0x1c): // INC E + OP(0x24): // INC H + OP(0x2c): // INC L + OP(0x3c): // INC A +OP_INC_R: + zR8(Opcode >> 3)++; + zF = (zF & CF) | SZHV_inc[zR8(Opcode >> 3)]; + RET(4) + + OP(0x34): // INC (HL) + adr = zHL; + +OP_INC_m: + res = READ_MEM8(adr); + res = (res + 1) & 0xff; + zF = (zF & CF) | SZHV_inc[res]; + WRITE_MEM8(adr, res); + RET(11) + +/*----------------------------------------- + DEC r8 +-----------------------------------------*/ + + OP(0x05): // DEC B + OP(0x0d): // DEC C + OP(0x15): // DEC D + OP(0x1d): // DEC E + OP(0x25): // DEC H + OP(0x2d): // DEC L + OP(0x3d): // DEC A +OP_DEC_R: + zR8(Opcode >> 3)--; + zF = (zF & CF) | SZHV_dec[zR8(Opcode >> 3)]; + RET(4) + + OP(0x35): // DEC (HL) + adr = zHL; + +OP_DEC_m: + res = READ_MEM8(adr); + res = (res - 1) & 0xff; + zF = (zF & CF) | SZHV_dec[res]; + WRITE_MEM8(adr, res); + RET(11) + +/*----------------------------------------- + ADD r8 +-----------------------------------------*/ + + OP(0x86): // ADD A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_ADD; + + OP(0xc6): // ADD A,n +OP_ADD_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_ADD; + + OP(0x80): // ADD A,B + OP(0x81): // ADD A,C + OP(0x82): // ADD A,D + OP(0x83): // ADD A,E + OP(0x84): // ADD A,H + OP(0x85): // ADD A,L + OP(0x87): // ADD A,A +OP_ADD_R: + val = zR8(Opcode & 7); + +OP_ADD: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT16 A = zA; + res = (UINT8)(A + val); + zF = SZHVC_add[(A << 8) | res]; + zA = res; + } +#else + res = zA + val; + zF = SZ[(UINT8)res] | ((res >> 8) & CF) | + ((zA ^ res ^ val) & HF) | + (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + ADC r8 +-----------------------------------------*/ + + OP(0x8e): // ADC A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_ADC; + + OP(0xce): // ADC A,n +OP_ADC_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_ADC; + + OP(0x88): // ADC A,B + OP(0x89): // ADC A,C + OP(0x8a): // ADC A,D + OP(0x8b): // ADC A,E + OP(0x8c): // ADC A,H + OP(0x8d): // ADC A,L + OP(0x8f): // ADC A,A +OP_ADC_R: + val = zR8(Opcode & 7); + +OP_ADC: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + UINT8 c = zF & CF; + res = (UINT8)(A + val + c); + zF = SZHVC_add[(c << 16) | (A << 8) | res]; + zA = res; + } +#else + res = zA + val + (zF & CF); + zF = SZ[res & 0xff] | ((res >> 8) & CF) | + ((zA ^ res ^ val) & HF) | + (((val ^ zA ^ 0x80) & (val ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + SUB r8 +-----------------------------------------*/ + + OP(0x96): // SUB (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_SUB; + + OP(0xd6): // SUB A,n +OP_SUB_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_SUB; + + OP(0x90): // SUB B + OP(0x91): // SUB C + OP(0x92): // SUB D + OP(0x93): // SUB E + OP(0x94): // SUB H + OP(0x95): // SUB L + OP(0x97): // SUB A +OP_SUB_R: + val = zR8(Opcode & 7); + +OP_SUB: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + res = (UINT8)(A - val); + zF = SZHVC_sub[(A << 8) | res]; + zA = res; + } +#else + res = zA - val; + zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + SBC r8 +-----------------------------------------*/ + + OP(0x9e): // SBC A,(HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_SBC; + + OP(0xde): // SBC A,n +OP_SBC_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_SBC; + + OP(0x98): // SBC A,B + OP(0x99): // SBC A,C + OP(0x9a): // SBC A,D + OP(0x9b): // SBC A,E + OP(0x9c): // SBC A,H + OP(0x9d): // SBC A,L + OP(0x9f): // SBC A,A +OP_SBC_R: + val = zR8(Opcode & 7); + +OP_SBC: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + UINT8 c = zF & CF; + res = (UINT8)(A - val - c); + zF = SZHVC_sub[(c << 16) | (A << 8) | res]; + zA = res; + } +#else + res = zA - val - (zF & CF); + zF = SZ[res & 0xff] | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) & 0x80) >> 5); + zA = res; +#endif + RET(4) + +/*----------------------------------------- + CP r8 +-----------------------------------------*/ + + OP(0xbe): // CP (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_CP; + + OP(0xfe): // CP n +OP_CP_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_CP; + + OP(0xb8): // CP B + OP(0xb9): // CP C + OP(0xba): // CP D + OP(0xbb): // CP E + OP(0xbc): // CP H + OP(0xbd): // CP L + OP(0xbf): // CP A +OP_CP_R: + val = zR8(Opcode & 7); + +OP_CP: +#if CZ80_BIG_FLAGS_ARRAY + { + UINT8 A = zA; + res = (UINT8)(A - val); + zF = (SZHVC_sub[(A << 8) | res] & ~(YF | XF)) | + (val & (YF | XF)); + } +#else + res = zA - val; + zF = (SZ[res & 0xff] & (SF | ZF)) | + (val & (YF | XF)) | ((res >> 8) & CF) | NF | + ((zA ^ res ^ val) & HF) | + (((val ^ zA) & (zA ^ res) >> 5) & VF); +#endif + RET(4) + +/*----------------------------------------- + AND r8 +-----------------------------------------*/ + + OP(0xa6): // AND (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_AND; + + OP(0xe6): // AND A,n +OP_AND_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_AND; + + OP(0xa0): // AND B + OP(0xa1): // AND C + OP(0xa2): // AND D + OP(0xa3): // AND E + OP(0xa4): // AND H + OP(0xa5): // AND L + OP(0xa7): // AND A +OP_AND_R: + val = zR8(Opcode & 7); + +OP_AND: + zA &= val; + zF = SZP[zA] | HF; + RET(4) + +/*----------------------------------------- + XOR r8 +-----------------------------------------*/ + + OP(0xae): // XOR (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_XOR; + + OP(0xee): // XOR A,n +OP_XOR_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_XOR; + + OP(0xa8): // XOR B + OP(0xa9): // XOR C + OP(0xaa): // XOR D + OP(0xab): // XOR E + OP(0xac): // XOR H + OP(0xad): // XOR L + OP(0xaf): // XOR A +OP_XOR_R: + val = zR8(Opcode & 7); + +OP_XOR: + zA ^= val; + zF = SZP[zA]; + RET(4) + +/*----------------------------------------- + OR r8 +-----------------------------------------*/ + + OP(0xb6): // OR (HL) + val = READ_MEM8(zHL); + USE_CYCLES(3) + goto OP_OR; + + OP(0xf6): // OR A,n +OP_OR_imm: + val = READ_ARG(); + USE_CYCLES(3) + goto OP_OR; + + OP(0xb0): // OR B + OP(0xb1): // OR C + OP(0xb2): // OR D + OP(0xb3): // OR E + OP(0xb4): // OR H + OP(0xb5): // OR L + OP(0xb7): // OR A +OP_OR_R: + val = zR8(Opcode & 7); + +OP_OR: + zA |= val; + zF = SZP[zA]; + RET(4) + +/*----------------------------------------- + MISC ARITHMETIC & CPU CONTROL +-----------------------------------------*/ + + OP(0x27): // DAA +OP_DAA: + { + UINT8 F; + UINT8 cf, nf, hf, lo, hi, diff; + + F = zF; + cf = F & CF; + nf = F & NF; + hf = F & HF; + lo = zA & 0x0f; + hi = zA >> 4; + + if (cf) + { + diff = (lo <= 9 && !hf) ? 0x60 : 0x66; + } + else + { + if (lo >= 10) + { + diff = hi <= 8 ? 0x06 : 0x66; + } + else + { + if (hi >= 10) + { + diff = hf ? 0x66 : 0x60; + } + else + { + diff = hf ? 0x06 : 0x00; + } + } + } + if (nf) zA -= diff; + else zA += diff; + + F = SZP[zA] | (F & NF); + if (cf || (lo <= 9 ? hi >= 10 : hi >= 9)) F |= CF; + if (nf ? hf && lo <= 5 : lo >= 10) F |= HF; + zF = F; + RET(4) + } + + OP(0x2f): // CPL +OP_CPL: + zA ^= 0xff; + zF = (zF & (SF | ZF | PF | CF)) | HF | NF | (zA & (YF | XF)); + RET(4) + + OP(0x37): // SCF +OP_SCF: + zF = (zF & (SF | ZF | PF)) | CF | (zA & (YF | XF)); + RET(4) + + OP(0x3f): // CCF +OP_CCF: + zF = ((zF & (SF | ZF | PF | CF)) | ((zF & CF) << 4) | (zA & (YF | XF))) ^ CF; + RET(4) + + OP(0x76): // HALT +OP_HALT: + CPU->HaltState = 1; + CPU->ICount = 0; + goto Cz80_Check_Interrupt; + + OP(0xf3): // DI +OP_DI: + zIFF = 0; + RET(4) + + OP(0xfb): // EI +OP_EI: + USE_CYCLES(4) + if (!zIFF1) + { + zIFF1 = zIFF2 = (1 << 2); + while (GET_OP() == 0xfb) + { + USE_CYCLES(4) + PC++; +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + } + if (CPU->IRQState) + { + afterEI = 1; + CPU->ExtraCycles += 1 - CPU->ICount; + CPU->ICount = 1; + } + } + else zIFF2 = (1 << 2); + goto Cz80_Exec_nocheck; + +/*----------------------------------------- + INC r16 +-----------------------------------------*/ + + OP(0x03): // INC BC +OP_INC_BC: + zBC++; + RET(6) + + OP(0x13): // INC DE +OP_INC_DE: + zDE++; + RET(6) + + OP(0x23): // INC HL +OP_INC_xx: + data->W++; + RET(6) + + OP(0x33): // INC SP +OP_INC_SP: + zSP++; + RET(6) + +/*----------------------------------------- + DEC r16 +-----------------------------------------*/ + + OP(0x0b): // DEC BC +OP_DEC_BC: + zBC--; + RET(6) + + OP(0x1b): // DEC DE +OP_DEC_DE: + zDE--; + RET(6) + + OP(0x2b): // DEC HL +OP_DEC_xx: + data->W--; + RET(6) + + OP(0x3b): // DEC SP +OP_DEC_SP: + zSP--; + RET(6) + +/*----------------------------------------- + ADD r16 +-----------------------------------------*/ + + OP(0x39): // ADD xx,SP +OP_ADD16_xx_SP: + val = zSP; + goto OP_ADD16; + + OP(0x29): // ADD xx,xx +OP_ADD16_xx_xx: + val = data->W; + goto OP_ADD16; + + OP(0x09): // ADD xx,BC +OP_ADD16_xx_BC: + val = zBC; + goto OP_ADD16; + + OP(0x19): // ADD xx,DE +OP_ADD16_xx_DE: + val = zDE; + +OP_ADD16: + res = data->W + val; + zF = (zF & (SF | ZF | VF)) | + (((data->W ^ res ^ val) >> 8) & HF) | + ((res >> 16) & CF) | ((res >> 8) & (YF | XF)); + data->W = (UINT16)res; + RET(11) + +/*----------------------------------------- + ROTATE +-----------------------------------------*/ + + { + UINT8 A; + UINT8 F; + + OP(0x07): // RLCA +OP_RLCA: + A = zA; + zA = (A << 1) | (A >> 7); + zF = (zF & (SF | ZF | PF)) | (zA & (YF | XF | CF)); + RET(4) + + OP(0x0f): // RRCA +OP_RRCA: + A = zA; + F = zF; + F = (F & (SF | ZF | PF)) | (A & CF); + zA = (A >> 1) | (A << 7); + zF = F | (zA & (YF | XF)); + RET(4) + + OP(0x17): // RLA +OP_RLA: + A = zA; + F = zF; + zA = (A << 1) | (F & CF); + zF = (F & (SF | ZF | PF)) | (A >> 7) | (zA & (YF | XF)); + RET(4) + + OP(0x1f): // RRA +OP_RRA: + A = zA; + F = zF; + zA = (A >> 1) | (F << 7); + zF = (F & (SF | ZF | PF)) | (A & CF) | (zA & (YF | XF)); + RET(4) + } + +/*----------------------------------------- + JP +-----------------------------------------*/ + + OP(0xc3): // JP nn +OP_JP: + res = READ_ARG16(); + SET_PC(res); + RET(10) + + OP(0xc2): // JP NZ,nn +OP_JP_NZ: + if (!(zF & ZF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xca): // JP Z,nn +OP_JP_Z: + if (zF & ZF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xd2): // JP NC,nn +OP_JP_NC: + if (!(zF & CF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xda): // JP C,nn +OP_JP_C: + if (zF & CF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xe2): // JP PO,nn +OP_JP_PO: + if (!(zF & VF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xea): // JP PE,nn +OP_JP_PE: + if (zF & VF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xf2): // JP P,nn +OP_JP_P: + if (!(zF & SF)) goto OP_JP; + PC += 2; + RET(10) + + OP(0xfa): // JP M,nn +OP_JP_M: + if (zF & SF) goto OP_JP; + PC += 2; + RET(10) + + OP(0xe9): // JP (xx) +OP_JP_xx: + res = data->W; + SET_PC(res); + RET(4) + +/*----------------------------------------- + JR +-----------------------------------------*/ + + OP(0x10): // DJNZ n +OP_DJNZ: + USE_CYCLES(1) + if (--zB) goto OP_JR; + PC++; + RET(7) + + OP(0x18): // JR n +OP_JR: + adr = (INT8)READ_ARG(); + PC += (INT8)adr; + RET(12) + + OP(0x20): // JR NZ,n +OP_JR_NZ: + if (!(zF & ZF)) goto OP_JR; + PC++; + RET(7) + + OP(0x28): // JR Z,n +OP_JR_Z: + if (zF & ZF) goto OP_JR; + PC++; + RET(7) + + OP(0x38): // JR C,n +OP_JR_C: + if (zF & CF) goto OP_JR; + PC++; + RET(7) + + OP(0x30): // JR NC,n +OP_JR_NC: + if (!(zF & CF)) goto OP_JR; + PC++; + RET(7) + +/*----------------------------------------- + CALL +-----------------------------------------*/ + + OP(0xcd): // CALL nn +OP_CALL: + res = READ_ARG16(); + val = zRealPC; + PUSH_16(val); + SET_PC(res); + RET(17) + + OP(0xc4): // CALL NZ,nn +OP_CALL_NZ: + if (!(zF & ZF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xcc): // CALL Z,nn +OP_CALL_Z: + if (zF & ZF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xd4): // CALL NC,nn +OP_CALL_NC: + if (!(zF & CF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xdc): // CALL C,nn +OP_CALL_C: + if (zF & CF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xe4): // CALL PO,nn +OP_CALL_PO: + if (!(zF & VF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xec): // CALL PE,nn +OP_CALL_PE: + if (zF & VF) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xf4): // CALL P,nn +OP_CALL_P: + if (!(zF & SF)) goto OP_CALL; + PC += 2; + RET(10) + + OP(0xfc): // CALL M,nn +OP_CALL_M: + if (zF & SF) goto OP_CALL; + PC += 2; + RET(10) + +/*----------------------------------------- + RET +-----------------------------------------*/ + +OP_RET_COND: + USE_CYCLES(1) + + OP(0xc9): // RET +OP_RET: + POP_16(res); + SET_PC(res); + RET(10) + + OP(0xc0): // RET NZ +OP_RET_NZ: + if (!(zF & ZF)) goto OP_RET_COND; + RET(5) + + OP(0xc8): // RET Z +OP_RET_Z: + if (zF & ZF) goto OP_RET_COND; + RET(5) + + OP(0xd0): // RET NC +OP_RET_NC: + if (!(zF & CF)) goto OP_RET_COND; + RET(5) + + OP(0xd8): // RET C +OP_RET_C: + if (zF & CF) goto OP_RET_COND; + RET(5) + + OP(0xe0): // RET PO +OP_RET_PO: + if (!(zF & VF)) goto OP_RET_COND; + RET(5) + + OP(0xe8): // RET PE +OP_RET_PE: + if (zF & VF) goto OP_RET_COND; + RET(5) + + OP(0xf0): // RET P +OP_RET_P: + if (!(zF & SF)) goto OP_RET_COND; + RET(5) + + OP(0xf8): // RET M +OP_RET_M: + if (zF & SF) goto OP_RET_COND; + RET(5) + +/*----------------------------------------- + RST +-----------------------------------------*/ + + OP(0xc7): // RST 0 + OP(0xcf): // RST 1 + OP(0xd7): // RST 2 + OP(0xdf): // RST 3 + OP(0xe7): // RST 4 + OP(0xef): // RST 5 + OP(0xf7): // RST 6 + OP(0xff): // RST 7 +OP_RST: + res = zRealPC; + PUSH_16(res); + res = Opcode & 0x38; + SET_PC(res); + RET(11) + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OP(0xd3): // OUT (n),A +OP_OUT_mN_A: + adr = (zA << 8) | READ_ARG(); + OUT(adr, zA); + RET(11) + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OP(0xdb): // IN A,(n) +OP_IN_A_mN: + adr = (zA << 8) | READ_ARG(); + zA = IN(adr); + RET(11) + +/*----------------------------------------- + PREFIX +-----------------------------------------*/ + + OP(0xcb): // CB prefix (BIT & SHIFT INSTRUCTIONS) + { + UINT8 src; + UINT8 res; + + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opCB.inc" + } + + OP(0xed): // ED prefix +ED_PREFIX: + USE_CYCLES(4) + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opED.inc" + + OP(0xdd): // DD prefix (IX) +DD_PREFIX: + data = pzIX; + goto XY_PREFIX; + + OP(0xfd): // FD prefix (IY) +FD_PREFIX: + data = pzIY; + +XY_PREFIX: + USE_CYCLES(4) + Opcode = READ_OP(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opXY.inc" + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/waterbox/picodrive/cpu/cz80/cz80_opCB.inc b/waterbox/picodrive/cpu/cz80/cz80_opCB.inc new file mode 100644 index 0000000000..58a78c53ed --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80_opCB.inc @@ -0,0 +1,470 @@ +/****************************************************************************** + * + * CZ80 CB opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableCB[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + RLC +-----------------------------------------*/ + + OPCB(0x00): // RLC B + OPCB(0x01): // RLC C + OPCB(0x02): // RLC D + OPCB(0x03): // RLC E + OPCB(0x04): // RLC H + OPCB(0x05): // RLC L + OPCB(0x07): // RLC A + src = zR8(Opcode); + res = (src << 1) | (src >> 7); + zF = SZP[res] | (src >> 7); + zR8(Opcode) = res; + RET(8) + + OPCB(0x06): // RLC (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | (src >> 7); + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RRC +-----------------------------------------*/ + + OPCB(0x08): // RRC B + OPCB(0x09): // RRC C + OPCB(0x0a): // RRC D + OPCB(0x0b): // RRC E + OPCB(0x0c): // RRC H + OPCB(0x0d): // RRC L + OPCB(0x0f): // RRC A + src = zR8(Opcode & 7); + res = (src >> 1) | (src << 7); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x0e): // RRC (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (src << 7); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RL +-----------------------------------------*/ + + OPCB(0x10): // RL B + OPCB(0x11): // RL C + OPCB(0x12): // RL D + OPCB(0x13): // RL E + OPCB(0x14): // RL H + OPCB(0x15): // RL L + OPCB(0x17): // RL A + src = zR8(Opcode & 7); + res = (src << 1) | (zF & CF); + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x16): // RL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | (zF & CF); + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + RR +-----------------------------------------*/ + + OPCB(0x18): // RR B + OPCB(0x19): // RR C + OPCB(0x1a): // RR D + OPCB(0x1b): // RR E + OPCB(0x1c): // RR H + OPCB(0x1d): // RR L + OPCB(0x1f): // RR A + src = zR8(Opcode & 7); + res = (src >> 1) | (zF << 7); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x1e): // RR (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (zF << 7); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SLA +-----------------------------------------*/ + + OPCB(0x20): // SLA B + OPCB(0x21): // SLA C + OPCB(0x22): // SLA D + OPCB(0x23): // SLA E + OPCB(0x24): // SLA H + OPCB(0x25): // SLA L + OPCB(0x27): // SLA A + src = zR8(Opcode & 7); + res = src << 1; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x26): // SLA (HL) + adr = zHL; + src = READ_MEM8(adr); + res = src << 1; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SRA +-----------------------------------------*/ + + OPCB(0x28): // SRA B + OPCB(0x29): // SRA C + OPCB(0x2a): // SRA D + OPCB(0x2b): // SRA E + OPCB(0x2c): // SRA H + OPCB(0x2d): // SRA L + OPCB(0x2f): // SRA A + src = zR8(Opcode & 7); + res = (src >> 1) | (src & 0x80); + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x2e): // SRA (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src >> 1) | (src & 0x80); + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SLL +-----------------------------------------*/ + + OPCB(0x30): // SLL B + OPCB(0x31): // SLL C + OPCB(0x32): // SLL D + OPCB(0x33): // SLL E + OPCB(0x34): // SLL H + OPCB(0x35): // SLL L + OPCB(0x37): // SLL A + src = zR8(Opcode & 7); + res = (src << 1) | 0x01; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x36): // SLL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = (src << 1) | 0x01; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SRL +-----------------------------------------*/ + + OPCB(0x38): // SRL B + OPCB(0x39): // SRL C + OPCB(0x3a): // SRL D + OPCB(0x3b): // SRL E + OPCB(0x3c): // SRL H + OPCB(0x3d): // SRL L + OPCB(0x3f): // SRL A + src = zR8(Opcode & 7); + res = src >> 1; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + RET(8) + + OPCB(0x3e): // SRL (HL) + adr = zHL; + src = READ_MEM8(adr); + res = src >> 1; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + BIT +-----------------------------------------*/ + + OPCB(0x40): // BIT 0,B + OPCB(0x41): // BIT 0,C + OPCB(0x42): // BIT 0,D + OPCB(0x43): // BIT 0,E + OPCB(0x44): // BIT 0,H + OPCB(0x45): // BIT 0,L + OPCB(0x47): // BIT 0,A + + OPCB(0x48): // BIT 1,B + OPCB(0x49): // BIT 1,C + OPCB(0x4a): // BIT 1,D + OPCB(0x4b): // BIT 1,E + OPCB(0x4c): // BIT 1,H + OPCB(0x4d): // BIT 1,L + OPCB(0x4f): // BIT 1,A + + OPCB(0x50): // BIT 2,B + OPCB(0x51): // BIT 2,C + OPCB(0x52): // BIT 2,D + OPCB(0x53): // BIT 2,E + OPCB(0x54): // BIT 2,H + OPCB(0x55): // BIT 2,L + OPCB(0x57): // BIT 2,A + + OPCB(0x58): // BIT 3,B + OPCB(0x59): // BIT 3,C + OPCB(0x5a): // BIT 3,D + OPCB(0x5b): // BIT 3,E + OPCB(0x5c): // BIT 3,H + OPCB(0x5d): // BIT 3,L + OPCB(0x5f): // BIT 3,A + + OPCB(0x60): // BIT 4,B + OPCB(0x61): // BIT 4,C + OPCB(0x62): // BIT 4,D + OPCB(0x63): // BIT 4,E + OPCB(0x64): // BIT 4,H + OPCB(0x65): // BIT 4,L + OPCB(0x67): // BIT 4,A + + OPCB(0x68): // BIT 5,B + OPCB(0x69): // BIT 5,C + OPCB(0x6a): // BIT 5,D + OPCB(0x6b): // BIT 5,E + OPCB(0x6c): // BIT 5,H + OPCB(0x6d): // BIT 5,L + OPCB(0x6f): // BIT 5,A + + OPCB(0x70): // BIT 6,B + OPCB(0x71): // BIT 6,C + OPCB(0x72): // BIT 6,D + OPCB(0x73): // BIT 6,E + OPCB(0x74): // BIT 6,H + OPCB(0x75): // BIT 6,L + OPCB(0x77): // BIT 6,A + + OPCB(0x78): // BIT 7,B + OPCB(0x79): // BIT 7,C + OPCB(0x7a): // BIT 7,D + OPCB(0x7b): // BIT 7,E + OPCB(0x7c): // BIT 7,H + OPCB(0x7d): // BIT 7,L + OPCB(0x7f): // BIT 7,A + zF = (zF & CF) | HF | SZ_BIT[zR8(Opcode & 7) & (1 << ((Opcode >> 3) & 7))]; + RET(8) + + OPCB(0x46): // BIT 0,(HL) + OPCB(0x4e): // BIT 1,(HL) + OPCB(0x56): // BIT 2,(HL) + OPCB(0x5e): // BIT 3,(HL) + OPCB(0x66): // BIT 4,(HL) + OPCB(0x6e): // BIT 5,(HL) + OPCB(0x76): // BIT 6,(HL) + OPCB(0x7e): // BIT 7,(HL) + src = READ_MEM8(zHL); + zF = (zF & CF) | HF | SZ_BIT[src & (1 << ((Opcode >> 3) & 7))]; + RET(12) + +/*----------------------------------------- + RES +-----------------------------------------*/ + + OPCB(0x80): // RES 0,B + OPCB(0x81): // RES 0,C + OPCB(0x82): // RES 0,D + OPCB(0x83): // RES 0,E + OPCB(0x84): // RES 0,H + OPCB(0x85): // RES 0,L + OPCB(0x87): // RES 0,A + + OPCB(0x88): // RES 1,B + OPCB(0x89): // RES 1,C + OPCB(0x8a): // RES 1,D + OPCB(0x8b): // RES 1,E + OPCB(0x8c): // RES 1,H + OPCB(0x8d): // RES 1,L + OPCB(0x8f): // RES 1,A + + OPCB(0x90): // RES 2,B + OPCB(0x91): // RES 2,C + OPCB(0x92): // RES 2,D + OPCB(0x93): // RES 2,E + OPCB(0x94): // RES 2,H + OPCB(0x95): // RES 2,L + OPCB(0x97): // RES 2,A + + OPCB(0x98): // RES 3,B + OPCB(0x99): // RES 3,C + OPCB(0x9a): // RES 3,D + OPCB(0x9b): // RES 3,E + OPCB(0x9c): // RES 3,H + OPCB(0x9d): // RES 3,L + OPCB(0x9f): // RES 3,A + + OPCB(0xa0): // RES 4,B + OPCB(0xa1): // RES 4,C + OPCB(0xa2): // RES 4,D + OPCB(0xa3): // RES 4,E + OPCB(0xa4): // RES 4,H + OPCB(0xa5): // RES 4,L + OPCB(0xa7): // RES 4,A + + OPCB(0xa8): // RES 5,B + OPCB(0xa9): // RES 5,C + OPCB(0xaa): // RES 5,D + OPCB(0xab): // RES 5,E + OPCB(0xac): // RES 5,H + OPCB(0xad): // RES 5,L + OPCB(0xaf): // RES 5,A + + OPCB(0xb0): // RES 6,B + OPCB(0xb1): // RES 6,C + OPCB(0xb2): // RES 6,D + OPCB(0xb3): // RES 6,E + OPCB(0xb4): // RES 6,H + OPCB(0xb5): // RES 6,L + OPCB(0xb7): // RES 6,A + + OPCB(0xb8): // RES 7,B + OPCB(0xb9): // RES 7,C + OPCB(0xba): // RES 7,D + OPCB(0xbb): // RES 7,E + OPCB(0xbc): // RES 7,H + OPCB(0xbd): // RES 7,L + OPCB(0xbf): // RES 7,A + zR8(Opcode & 7) &= ~(1 << ((Opcode >> 3) & 7)); + RET(8) + + OPCB(0x86): // RES 0,(HL) + OPCB(0x8e): // RES 1,(HL) + OPCB(0x96): // RES 2,(HL) + OPCB(0x9e): // RES 3,(HL) + OPCB(0xa6): // RES 4,(HL) + OPCB(0xae): // RES 5,(HL) + OPCB(0xb6): // RES 6,(HL) + OPCB(0xbe): // RES 7,(HL) + adr = zHL; + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + WRITE_MEM8(adr, res); + RET(15) + +/*----------------------------------------- + SET +-----------------------------------------*/ + + OPCB(0xc0): // SET 0,B + OPCB(0xc1): // SET 0,C + OPCB(0xc2): // SET 0,D + OPCB(0xc3): // SET 0,E + OPCB(0xc4): // SET 0,H + OPCB(0xc5): // SET 0,L + OPCB(0xc7): // SET 0,A + + OPCB(0xc8): // SET 1,B + OPCB(0xc9): // SET 1,C + OPCB(0xca): // SET 1,D + OPCB(0xcb): // SET 1,E + OPCB(0xcc): // SET 1,H + OPCB(0xcd): // SET 1,L + OPCB(0xcf): // SET 1,A + + OPCB(0xd0): // SET 2,B + OPCB(0xd1): // SET 2,C + OPCB(0xd2): // SET 2,D + OPCB(0xd3): // SET 2,E + OPCB(0xd4): // SET 2,H + OPCB(0xd5): // SET 2,L + OPCB(0xd7): // SET 2,A + + OPCB(0xd8): // SET 3,B + OPCB(0xd9): // SET 3,C + OPCB(0xda): // SET 3,D + OPCB(0xdb): // SET 3,E + OPCB(0xdc): // SET 3,H + OPCB(0xdd): // SET 3,L + OPCB(0xdf): // SET 3,A + + OPCB(0xe0): // SET 4,B + OPCB(0xe1): // SET 4,C + OPCB(0xe2): // SET 4,D + OPCB(0xe3): // SET 4,E + OPCB(0xe4): // SET 4,H + OPCB(0xe5): // SET 4,L + OPCB(0xe7): // SET 4,A + + OPCB(0xe8): // SET 5,B + OPCB(0xe9): // SET 5,C + OPCB(0xea): // SET 5,D + OPCB(0xeb): // SET 5,E + OPCB(0xec): // SET 5,H + OPCB(0xed): // SET 5,L + OPCB(0xef): // SET 5,A + + OPCB(0xf0): // SET 6,B + OPCB(0xf1): // SET 6,C + OPCB(0xf2): // SET 6,D + OPCB(0xf3): // SET 6,E + OPCB(0xf4): // SET 6,H + OPCB(0xf5): // SET 6,L + OPCB(0xf7): // SET 6,A + + OPCB(0xf8): // SET 7,B + OPCB(0xf9): // SET 7,C + OPCB(0xfa): // SET 7,D + OPCB(0xfb): // SET 7,E + OPCB(0xfc): // SET 7,H + OPCB(0xfd): // SET 7,L + OPCB(0xff): // SET 7,A + zR8(Opcode & 7) |= 1 << ((Opcode >> 3) & 7); + RET(8) + + OPCB(0xc6): // SET 0,(HL) + OPCB(0xce): // SET 1,(HL) + OPCB(0xd6): // SET 2,(HL) + OPCB(0xde): // SET 3,(HL) + OPCB(0xe6): // SET 4,(HL) + OPCB(0xee): // SET 5,(HL) + OPCB(0xf6): // SET 6,(HL) + OPCB(0xfe): // SET 7,(HL) + adr = zHL; + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + WRITE_MEM8(adr, res); + RET(15) + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/waterbox/picodrive/cpu/cz80/cz80_opED.inc b/waterbox/picodrive/cpu/cz80/cz80_opED.inc new file mode 100644 index 0000000000..c3b7ec64d1 --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80_opED.inc @@ -0,0 +1,731 @@ +/****************************************************************************** + * + * CZ80 ED opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableED[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + ILLEGAL +-----------------------------------------*/ + + OPED(0x00): + OPED(0x01): + OPED(0x02): + OPED(0x03): + OPED(0x04): + OPED(0x05): + OPED(0x06): + OPED(0x07): + OPED(0x08): + OPED(0x09): + OPED(0x0a): + OPED(0x0b): + OPED(0x0c): + OPED(0x0d): + OPED(0x0e): + OPED(0x0f): + + OPED(0x10): + OPED(0x11): + OPED(0x12): + OPED(0x13): + OPED(0x14): + OPED(0x15): + OPED(0x16): + OPED(0x17): + OPED(0x18): + OPED(0x19): + OPED(0x1a): + OPED(0x1b): + OPED(0x1c): + OPED(0x1d): + OPED(0x1e): + OPED(0x1f): + + OPED(0x20): + OPED(0x21): + OPED(0x22): + OPED(0x23): + OPED(0x24): + OPED(0x25): + OPED(0x26): + OPED(0x27): + OPED(0x28): + OPED(0x29): + OPED(0x2a): + OPED(0x2b): + OPED(0x2c): + OPED(0x2d): + OPED(0x2e): + OPED(0x2f): + + OPED(0x30): + OPED(0x31): + OPED(0x32): + OPED(0x33): + OPED(0x34): + OPED(0x35): + OPED(0x36): + OPED(0x37): + OPED(0x38): + OPED(0x39): + OPED(0x3a): + OPED(0x3b): + OPED(0x3c): + OPED(0x3d): + OPED(0x3e): + OPED(0x3f): + + OPED(0x77): + OPED(0x7f): + + OPED(0x80): + OPED(0x81): + OPED(0x82): + OPED(0x83): + OPED(0x84): + OPED(0x85): + OPED(0x86): + OPED(0x87): + OPED(0x88): + OPED(0x89): + OPED(0x8a): + OPED(0x8b): + OPED(0x8c): + OPED(0x8d): + OPED(0x8e): + OPED(0x8f): + + OPED(0x90): + OPED(0x91): + OPED(0x92): + OPED(0x93): + OPED(0x94): + OPED(0x95): + OPED(0x96): + OPED(0x97): + OPED(0x98): + OPED(0x99): + OPED(0x9a): + OPED(0x9b): + OPED(0x9c): + OPED(0x9d): + OPED(0x9e): + OPED(0x9f): + + OPED(0xa4): + OPED(0xa5): + OPED(0xa6): + OPED(0xa7): + + OPED(0xac): + OPED(0xad): + OPED(0xae): + OPED(0xaf): + + OPED(0xb4): + OPED(0xb5): + OPED(0xb6): + OPED(0xb7): + + OPED(0xbc): + OPED(0xbd): + OPED(0xbe): + OPED(0xbf): + + OPED(0xc0): + OPED(0xc1): + OPED(0xc2): + OPED(0xc3): + OPED(0xc4): + OPED(0xc5): + OPED(0xc6): + OPED(0xc7): + OPED(0xc8): + OPED(0xc9): + OPED(0xca): + OPED(0xcb): + OPED(0xcc): + OPED(0xcd): + OPED(0xce): + OPED(0xcf): + + OPED(0xd0): + OPED(0xd1): + OPED(0xd2): + OPED(0xd3): + OPED(0xd4): + OPED(0xd5): + OPED(0xd6): + OPED(0xd7): + OPED(0xd8): + OPED(0xd9): + OPED(0xda): + OPED(0xdb): + OPED(0xdc): + OPED(0xdd): + OPED(0xde): + OPED(0xdf): + + OPED(0xe0): + OPED(0xe1): + OPED(0xe2): + OPED(0xe3): + OPED(0xe4): + OPED(0xe5): + OPED(0xe6): + OPED(0xe7): + OPED(0xe8): + OPED(0xe9): + OPED(0xea): + OPED(0xeb): + OPED(0xec): + OPED(0xed): + OPED(0xee): + OPED(0xef): + + OPED(0xf0): + OPED(0xf1): + OPED(0xf2): + OPED(0xf3): + OPED(0xf4): + OPED(0xf5): + OPED(0xf6): + OPED(0xf7): + OPED(0xf8): + OPED(0xf9): + OPED(0xfa): + OPED(0xfb): + OPED(0xfc): + OPED(0xfd): + OPED(0xfe): + OPED(0xff): + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OPED(0x47): // LD I,A + zI = zA; + RET(5) + + OPED(0x4f): // LD R,A +#if CZ80_EMULATE_R_EXACTLY + zR = zA; +#else + zR = zA - ((cycles - CPU->ICount) >> 2); +#endif + zR2 = zA & 0x80; + RET(5) + + OPED(0x57): // LD A,I + zA = zI; + zF = (zF & CF) | SZ[zA] | zIFF2; + RET(5) + + OPED(0x5f): // LD A,R +#if CZ80_EMULATE_R_EXACTLY + zA = (zR & 0x7f) | zR2; +#else + zA = ((zR + ((cycles - CPU->ICount) >> 2)) & 0x7f) | zR2; +#endif + zF = (zF & CF) | SZ[zA] | zIFF2; + RET(5) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OPED(0x43): // LD (w),BC + data = pzBC; + goto OP_LD_mNN_xx; + + OPED(0x53): // LD (w),DE + data = pzDE; + goto OP_LD_mNN_xx; + + OPED(0x63): // LD (w),HL + data = pzHL; + goto OP_LD_mNN_xx; + + OPED(0x73): // LD (w),SP + data = pzSP; + goto OP_LD_mNN_xx; + + OPED(0x4b): // LD BC,(w) + data = pzBC; + goto OP_LD_xx_mNN; + + OPED(0x5b): // LD DE,(w) + data = pzDE; + goto OP_LD_xx_mNN; + + OPED(0x6b): // LD HL,(w) + data = pzHL; + goto OP_LD_xx_mNN; + + OPED(0x7b): // LD SP,(w) + data = pzSP; + goto OP_LD_xx_mNN; + +/*----------------------------------------- + NEG +-----------------------------------------*/ + + OPED(0x44): // NEG + OPED(0x4c): // NEG + OPED(0x54): // NEG + OPED(0x5c): // NEG + OPED(0x64): // NEG + OPED(0x6c): // NEG + OPED(0x74): // NEG + OPED(0x7c): // NEG + val = zA; + zA = 0; + goto OP_SUB; + +/*----------------------------------------- + RRD +-----------------------------------------*/ + + OPED(0x67): // RRD (HL) + adr = zHL; + val = READ_MEM8(adr); + WRITE_MEM8(adr, (val >> 4) | (zA << 4)); + zA = (zA & 0xf0) | (val & 0x0f); + zF = (zF & CF) | SZP[zA]; + RET(14) + +/*----------------------------------------- + RLD +-----------------------------------------*/ + + OPED(0x6f): // RLD (HL) + adr = zHL; + val = READ_MEM8(adr); + WRITE_MEM8(adr, (val << 4) | (zA & 0x0f)); + zA = (zA & 0xf0) | (val >> 4); + zF = (zF & CF) | SZP[zA]; + RET(14) + +/*----------------------------------------- + ADC 16 +-----------------------------------------*/ + + OPED(0x7a): // ADC HL,SP + val = zSP; + goto OP_ADC16; + + OPED(0x4a): // ADC HL,BC + OPED(0x5a): // ADC HL,DE + OPED(0x6a): // ADC HL,HL + val = zR16((Opcode >> 4) & 3); + +OP_ADC16: + res = zHL + val + (zF & CF); + zF = (((zHL ^ res ^ val) >> 8) & HF) | + ((res >> 16) & CF) | + ((res >> 8) & (SF | YF | XF)) | + ((res & 0xffff) ? 0 : ZF) | + (((val ^ zHL ^ 0x8000) & (val ^ res) & 0x8000) >> 13); + zHL = (UINT16)res; + RET(11) + +/*----------------------------------------- + SBC 16 +-----------------------------------------*/ + + OPED(0x72): // SBC HL,SP + val = zSP; + goto OP_SBC16; + + OPED(0x42): // SBC HL,BC + OPED(0x52): // SBC HL,DE + OPED(0x62): // SBC HL,HL + val = zR16((Opcode >> 4) & 3); + +OP_SBC16: + res = zHL - val - (zF & CF); + zF = (((zHL ^ res ^ val) >> 8) & HF) | NF | + ((res >> 16) & CF) | + ((res >> 8) & (SF | YF | XF)) | + ((res & 0xffff) ? 0 : ZF) | + (((val ^ zHL) & (zHL ^ res) & 0x8000) >> 13); + zHL = (UINT16)res; + RET(11) + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OPED(0x40): // IN B,(C) + OPED(0x48): // IN C,(C) + OPED(0x50): // IN D,(C) + OPED(0x58): // IN E,(C) + OPED(0x60): // IN H,(C) + OPED(0x68): // IN L,(C) + OPED(0x78): // IN E,(C) + res = IN(zBC); + zR8((Opcode >> 3) & 7) = res; + zF = (zF & CF) | SZP[res]; + RET(8) + + OPED(0x70): // IN 0,(C) + res = IN(zBC); + zF = (zF & CF) | SZP[res]; + RET(8) + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OPED(0x51): // OUT (C),D + OPED(0x41): // OUT (C),B + OPED(0x49): // OUT (C),C + OPED(0x59): // OUT (C),E + OPED(0x61): // OUT (C),H + OPED(0x69): // OUT (C),L + OPED(0x79): // OUT (C),E + res = zR8((Opcode >> 3) & 7); + OUT(zBC, res); + RET(8) + + OPED(0x71): // OUT (C),0 + OUT(zBC, 0); + RET(8) + +/*----------------------------------------- + RETN +-----------------------------------------*/ + + OPED(0x45): // RETN; + OPED(0x55): // RETN; + OPED(0x65): // RETN; + OPED(0x75): // RETN; + POP_16(res); + SET_PC(res); + if (!zIFF1 && zIFF2) + { + zIFF1 = (1 << 2); + if (CPU->IRQState) + { + USE_CYCLES(10) + goto Cz80_Check_Interrupt; + } + } + else zIFF1 = zIFF2; + RET(10) + +/*----------------------------------------- + RETI +-----------------------------------------*/ + + OPED(0x4d): // RETI + OPED(0x5d): // RETI + OPED(0x6d): // RETI + OPED(0x7d): // RETI + POP_16(res); + SET_PC(res); + RET(10) + +/*----------------------------------------- + IM +-----------------------------------------*/ + + OPED(0x46): // IM 0 + OPED(0x4e): // IM 0 + OPED(0x66): // IM 0 + OPED(0x6e): // IM 0 + zIM = 0; + RET(4) + + OPED(0x56): // IM 1 + OPED(0x76): // IM 1 + zIM = 1; + RET(4) + + OPED(0x5e): // IM 2 + OPED(0x7e): // IM 2 + zIM = 2; + RET(4) + + { + UINT8 val; + UINT8 res; + UINT8 F; + +/*----------------------------------------- + LDI/LDD +-----------------------------------------*/ + + OPED(0xa0): // LDI + val = READ_MEM8(zHL++); + WRITE_MEM8(zDE++, val); + goto OP_LDX; + + OPED(0xa8): // LDD + val = READ_MEM8(zHL--); + WRITE_MEM8(zDE--, val); + +OP_LDX: + F = zF & (SF | ZF | CF); + if ((zA + val) & 0x02) F |= YF; + if ((zA + val) & 0x08) F |= XF; + if (--zBC) F |= VF; + zF = F; + RET(12) + +/*----------------------------------------- + LDIR/LDDR +-----------------------------------------*/ + + OPED(0xb0): // LDIR + do + { + val = READ_MEM8(zHL++); + WRITE_MEM8(zDE++, val); + zBC--; + USE_CYCLES(17) + } while (zBC && (CPU->ICount > 0)); + goto OP_LDXR; + + OPED(0xb8): // LDDR + do + { + val = READ_MEM8(zHL--); + WRITE_MEM8(zDE--, val); + zBC--; + USE_CYCLES(17) + } while (zBC && (CPU->ICount > 0)); + +OP_LDXR: + F = zF & (SF | ZF | CF); + if ((zA + val) & 0x02) F |= YF; + if ((zA + val) & 0x08) F |= XF; + if (zBC) + { + zF = F | VF; + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + zF = F; + ADD_CYCLES(5) + goto Cz80_Exec; + +/*----------------------------------------- + CPI/CPD +-----------------------------------------*/ + + OPED(0xa1): // CPI + val = READ_MEM8(zHL++); + goto OP_CPX; + + OPED(0xa9): // CPD + val = READ_MEM8(zHL--); + +OP_CPX: + res = zA - val; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (--zBC) F |= VF; + zF = F; + RET(12) + +/*----------------------------------------- + CPIR/CPDR +-----------------------------------------*/ + + OPED(0xb1): // CPIR + do + { + val = READ_MEM8(zHL++); + res = zA - val; + zBC--; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (zBC) F |= VF; + zF = F; + USE_CYCLES(17) + } while (zBC && !(F & ZF) && (CPU->ICount > 0)); + goto OP_CPXR; + + OPED(0xb9): // CPDR + do + { + val = READ_MEM8(zHL--); + res = zA - val; + zBC--; + F = (zF & CF) | (SZ[res] & ~(YF | XF)) | ((zA ^ val ^ res) & HF) | NF; + if (F & HF) res--; + if (res & 0x02) F |= YF; + if (res & 0x08) F |= XF; + if (zBC) F |= VF; + zF = F; + USE_CYCLES(17) + } while (zBC && !(F & ZF) && (CPU->ICount > 0)); + +OP_CPXR: + if (zBC && !(F & ZF)) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5) + goto Cz80_Exec; + +/*----------------------------------------- + INI/IND +-----------------------------------------*/ + + OPED(0xa2): // INI + val = IN(zBC); + zB--; + WRITE_MEM8(zHL++, val); + goto OP_INX; + + OPED(0xaa): // IND + val = IN(zBC); + zB--; + WRITE_MEM8(zHL--, val); + +OP_INX: + F = SZ[zB]; + res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF; + zF = F; + RET(12) + +/*----------------------------------------- + INIR/INDR +-----------------------------------------*/ + + OPED(0xb2): // INIR + do + { + val = IN(zBC); + zB--; + WRITE_MEM8(zHL++, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + goto OP_INXR; + + OPED(0xba): // INDR + do + { + val = IN(zBC); + zB--; + WRITE_MEM8(zHL--, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + +OP_INXR: + F = SZ[zB]; + res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF; + zF = F; + if (zB) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5); + goto Cz80_Exec; + +/*----------------------------------------- + OUTI/OUTD +-----------------------------------------*/ + + OPED(0xa3): // OUTI + val = READ_MEM8(zHL++); + zB--; + OUT(zBC, val); + goto OP_OUTX; + + OPED(0xab): // OUTD + val = READ_MEM8(zHL--); + zB--; + OUT(zBC, val); + +OP_OUTX: + F = SZ[zB]; + res = (UINT32)zL + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) - zB] & PF; + zF = F; + RET(12) + +/*----------------------------------------- + OTIR/OTDR +-----------------------------------------*/ + + OPED(0xb3): // OTIR + do + { + val = READ_MEM8(zHL++); + zB--; + OUT(zBC, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + goto OP_OTXR; + + OPED(0xbb): // OTDR + do + { + val = READ_MEM8(zHL--); + zB--; + OUT(zBC, val); + USE_CYCLES(17) + } while (zB && (CPU->ICount > 0)); + +OP_OTXR: + F = SZ[zB]; + res = (UINT32)zL + (UINT32)val; + if (val & SF) F |= NF; + if (res & 0x100) F |= HF | CF; + F |= SZP[(UINT8)(res & 0x07) - zB] & PF; + zF = F; + if (zB) + { + PC -= 2; +#if CZ80_EMULATE_R_EXACTLY + zR--; +#endif + goto Cz80_Exec_End; + } + ADD_CYCLES(5) + goto Cz80_Exec; + } + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/waterbox/picodrive/cpu/cz80/cz80_opXY.inc b/waterbox/picodrive/cpu/cz80/cz80_opXY.inc new file mode 100644 index 0000000000..db0b02963f --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80_opXY.inc @@ -0,0 +1,786 @@ +/****************************************************************************** + * + * CZ80 XY opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 St�phane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableXY[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + NOP +-----------------------------------------*/ + + OPXY(0x00): // NOP + +/*----------------------------------------- + LD r8 (same register) +-----------------------------------------*/ + + OPXY(0x40): // LD B,B + OPXY(0x49): // LD C,C + OPXY(0x52): // LD D,D + OPXY(0x5b): // LD E,E + OPXY(0x64): // LD H,H + OPXY(0x6d): // LD L,L + OPXY(0x7f): // LD A,A + RET(4) + +/*----------------------------------------- + LD r8 +-----------------------------------------*/ + + OPXY(0x41): // LD B,C + OPXY(0x42): // LD B,D + OPXY(0x43): // LD B,E + OPXY(0x47): // LD B,A + + OPXY(0x48): // LD C,B + OPXY(0x4a): // LD C,D + OPXY(0x4b): // LD C,E + OPXY(0x4f): // LD C,A + + OPXY(0x50): // LD D,B + OPXY(0x51): // LD D,C + OPXY(0x53): // LD D,E + OPXY(0x57): // LD D,A + + OPXY(0x58): // LD E,B + OPXY(0x59): // LD E,C + OPXY(0x5a): // LD E,D + OPXY(0x5f): // LD E,A + + OPXY(0x78): // LD A,B + OPXY(0x79): // LD A,C + OPXY(0x7a): // LD A,D + OPXY(0x7b): // LD A,E + goto OP_LD_R_R; + + OPXY(0x44): // LD B,HX + OPXY(0x4c): // LD C,HX + OPXY(0x54): // LD D,HX + OPXY(0x5c): // LD E,HX + OPXY(0x7c): // LD A,HX + zR8((Opcode >> 3) & 7) = data->B.H; + RET(5) + + OPXY(0x45): // LD B,LX + OPXY(0x4d): // LD C,LX + OPXY(0x55): // LD D,LX + OPXY(0x5d): // LD E,LX + OPXY(0x7d): // LD A,LX + zR8((Opcode >> 3) & 7) = data->B.L; + RET(5) + + OPXY(0x60): // LD HX,B + OPXY(0x61): // LD HX,C + OPXY(0x62): // LD HX,D + OPXY(0x63): // LD HX,E + OPXY(0x67): // LD HX,A + data->B.H = zR8(Opcode & 7); + RET(5) + + OPXY(0x68): // LD LX,B + OPXY(0x69): // LD LX,C + OPXY(0x6a): // LD LX,D + OPXY(0x6b): // LD LX,E + OPXY(0x6f): // LD LX,A + data->B.L = zR8(Opcode & 7); + RET(5) + + OPXY(0x65): // LD HX,LX + data->B.H = data->B.L; + RET(5) + + OPXY(0x6c): // LD LX,HX + data->B.L = data->B.H; + RET(5) + + OPXY(0x06): // LD B,#imm + OPXY(0x0e): // LD C,#imm + OPXY(0x16): // LD D,#imm + OPXY(0x1e): // LD E,#imm + OPXY(0x3e): // LD A,#imm + goto OP_LD_R_imm; + + OPXY(0x26): // LD HX,#imm + data->B.H = READ_ARG(); + RET(5) + + OPXY(0x2e): // LD LX,#imm + data->B.L = READ_ARG(); + RET(5) + + OPXY(0x0a): // LD A,(BC) + goto OP_LOAD_A_mBC; + + OPXY(0x1a): // LD A,(DE) + goto OP_LOAD_A_mDE; + + OPXY(0x3a): // LD A,(nn) + goto OP_LOAD_A_mNN; + + OPXY(0x02): // LD (BC),A + goto OP_LOAD_mBC_A; + + OPXY(0x12): // LD (DE),A + goto OP_LOAD_mDE_A; + + OPXY(0x32): // LD (nn),A + goto OP_LOAD_mNN_A; + + OPXY(0x46): // LD B,(IX+o) + OPXY(0x4e): // LD C,(IX+o) + OPXY(0x56): // LD D,(IX+o) + OPXY(0x5e): // LD E,(IX+o) + OPXY(0x66): // LD H,(IX+o) + OPXY(0x6e): // LD L,(IX+o) + OPXY(0x7e): // LD A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + zR8((Opcode >> 3) & 7) = READ_MEM8(adr); + RET(15) + + OPXY(0x70): // LD (IX+o),B + OPXY(0x71): // LD (IX+o),C + OPXY(0x72): // LD (IX+o),D + OPXY(0x73): // LD (IX+o),E + OPXY(0x74): // LD (IX+o),H + OPXY(0x75): // LD (IX+o),L + OPXY(0x77): // LD (IX+o),A + adr = data->W + (INT8)READ_ARG(); + WRITE_MEM8(adr, zR8(Opcode & 7)); + RET(15) + + OPXY(0x36): // LD (IX+o),#imm + adr = data->W + (INT8)READ_ARG(); + WRITE_MEM8(adr, READ_ARG()); + RET(15) + +/*----------------------------------------- + LD r16 +-----------------------------------------*/ + + OPXY(0x01): // LD BC,nn + OPXY(0x11): // LD DE,nn + goto OP_LOAD_RR_imm16; + + OPXY(0x21): // LD IX,nn + data->W = READ_ARG16(); + RET(10) + + OPXY(0x31): // LD SP,nn + goto OP_LOAD_SP_imm16; + + OPXY(0x2a): // LD IX,(w) + goto OP_LD_xx_mNN; + + OPXY(0x22): // LD (w),IX + goto OP_LD_mNN_xx; + + OPXY(0xf9): // LD SP,IX + goto OP_LD_SP_xx; + +/*----------------------------------------- + POP +-----------------------------------------*/ + + OPXY(0xc1): // POP BC + OPXY(0xd1): // POP DE + OPXY(0xf1): // POP AF + goto OP_POP_RR; + + OPXY(0xe1): // POP IX + goto OP_POP; + +/*----------------------------------------- + PUSH +-----------------------------------------*/ + + OPXY(0xc5): // PUSH BC + OPXY(0xd5): // PUSH DE + OPXY(0xf5): // PUSH AF + goto OP_PUSH_RR; + + OPXY(0xe5): // PUSH IX + goto OP_PUSH; + +/*----------------------------------------- + EX +-----------------------------------------*/ + + OPXY(0x08): // EX AF,AF' + goto OP_EX_AF_AF2; + + OPXY(0xeb): // EX DE,HL + goto OP_EX_DE_HL; + + OPXY(0xd9): // EXX + goto OP_EXX; + + OPXY(0xe3): // EX (SP),IX + goto OP_EX_xx_mSP; + +/*----------------------------------------- + INC r8 +-----------------------------------------*/ + + OPXY(0x04): // INC B + OPXY(0x0c): // INC C + OPXY(0x14): // INC D + OPXY(0x1c): // INC E + OPXY(0x3c): // INC A + goto OP_INC_R; + + OPXY(0x24): // INC HX + data->B.H++; + zF = (zF & CF) | SZHV_inc[data->B.H]; + RET(5) + + OPXY(0x2c): // INC LX + data->B.L++; + zF = (zF & CF) | SZHV_inc[data->B.L]; + RET(5) + + OPXY(0x34): // INC (IX+o) + adr = data->W + (INT8)READ_ARG(); + USE_CYCLES(8) + goto OP_INC_m; + +/*----------------------------------------- + DEC r8 +-----------------------------------------*/ + + OPXY(0x05): // DEC B + OPXY(0x0d): // DEC C + OPXY(0x15): // DEC D + OPXY(0x1d): // DEC E + OPXY(0x3d): // DEC A + goto OP_DEC_R; + + OPXY(0x25): // DEC HX + data->B.H--; + zF = (zF & CF) | SZHV_dec[data->B.H]; + RET(5) + + OPXY(0x2d): // DEC LX + data->B.L--; + zF = (zF & CF) | SZHV_dec[data->B.L]; + RET(5) + + OPXY(0x35): // DEC (IX+o) + adr = data->W + (INT8)READ_ARG(); + USE_CYCLES(8) + goto OP_DEC_m; + +/*----------------------------------------- + ADD r8 +-----------------------------------------*/ + + OPXY(0x80): // ADD A,B + OPXY(0x81): // ADD A,C + OPXY(0x82): // ADD A,D + OPXY(0x83): // ADD A,E + OPXY(0x87): // ADD A,A + goto OP_ADD_R; + + OPXY(0xc6): // ADD A,n + goto OP_ADD_imm; + + OPXY(0x84): // ADD A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_ADD; + + OPXY(0x85): // ADD A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_ADD; + + OPXY(0x86): // ADD A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_ADD; + +/*----------------------------------------- + ADC r8 +-----------------------------------------*/ + + OPXY(0x88): // ADC A,B + OPXY(0x89): // ADC A,C + OPXY(0x8a): // ADC A,D + OPXY(0x8b): // ADC A,E + OPXY(0x8f): // ADC A,A + goto OP_ADC_R; + + OPXY(0xce): // ADC A,n + goto OP_ADC_imm; + + OPXY(0x8c): // ADC A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_ADC; + + OPXY(0x8d): // ADC A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_ADC; + + OPXY(0x8e): // ADC A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_ADC; + +/*----------------------------------------- + SUB r8 +-----------------------------------------*/ + + OPXY(0x90): // SUB B + OPXY(0x91): // SUB C + OPXY(0x92): // SUB D + OPXY(0x93): // SUB E + OPXY(0x97): // SUB A + goto OP_SUB_R; + + OPXY(0xd6): // SUB A,n + goto OP_SUB_imm; + + OPXY(0x94): // SUB HX + val = data->B.H; + USE_CYCLES(1) + goto OP_SUB; + + OPXY(0x95): // SUB LX + val = data->B.L; + USE_CYCLES(1) + goto OP_SUB; + + OPXY(0x96): // SUB (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_SUB; + +/*----------------------------------------- + SBC r8 +-----------------------------------------*/ + + OPXY(0x98): // SBC A,B + OPXY(0x99): // SBC A,C + OPXY(0x9a): // SBC A,D + OPXY(0x9b): // SBC A,E + OPXY(0x9f): // SBC A,A + goto OP_SBC_R; + + OPXY(0xde): // SBC A,n + goto OP_SBC_imm; + + OPXY(0x9c): // SBC A,HX + val = data->B.H; + USE_CYCLES(1) + goto OP_SBC; + + OPXY(0x9d): // SBC A,LX + val = data->B.L; + USE_CYCLES(1) + goto OP_SBC; + + OPXY(0x9e): // SBC A,(IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_SBC; + +/*----------------------------------------- + CP r8 +-----------------------------------------*/ + + OPXY(0xb8): // CP B + OPXY(0xb9): // CP C + OPXY(0xba): // CP D + OPXY(0xbb): // CP E + OPXY(0xbf): // CP A + goto OP_CP_R; + + OPXY(0xfe): // CP n + goto OP_CP_imm; + + OPXY(0xbc): // CP HX + val = data->B.H; + USE_CYCLES(1) + goto OP_CP; + + OPXY(0xbd): // CP LX + val = data->B.L; + USE_CYCLES(1) + goto OP_CP; + + OPXY(0xbe): // CP (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_CP; + +/*----------------------------------------- + AND r8 +-----------------------------------------*/ + + OPXY(0xa0): // AND B + OPXY(0xa1): // AND C + OPXY(0xa2): // AND D + OPXY(0xa3): // AND E + OPXY(0xa7): // AND A + goto OP_AND_R; + + OPXY(0xe6): // AND A,n + goto OP_AND_imm; + + OPXY(0xa4): // AND HX + val = data->B.H; + USE_CYCLES(1) + goto OP_AND; + + OPXY(0xa5): // AND LX + val = data->B.L; + USE_CYCLES(1) + goto OP_AND; + + OPXY(0xa6): // AND (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_AND; + +/*----------------------------------------- + XOR r8 +-----------------------------------------*/ + + OPXY(0xa8): // XOR B + OPXY(0xa9): // XOR C + OPXY(0xaa): // XOR D + OPXY(0xab): // XOR E + OPXY(0xaf): // XOR A + goto OP_XOR_R; + + OPXY(0xee): // XOR A,n + goto OP_XOR_imm; + + OPXY(0xac): // XOR HX + val = data->B.H; + USE_CYCLES(1) + goto OP_XOR; + + OPXY(0xad): // XOR LX + val = data->B.L; + USE_CYCLES(1) + goto OP_XOR; + + OPXY(0xae): // XOR (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_XOR; + +/*----------------------------------------- + OR r8 +-----------------------------------------*/ + + OPXY(0xb0): // OR B + OPXY(0xb1): // OR C + OPXY(0xb2): // OR D + OPXY(0xb3): // OR E + OPXY(0xb7): // OR A + goto OP_OR_R; + + OPXY(0xf6): // OR A,n + goto OP_OR_imm; + + OPXY(0xb4): // OR HX + val = data->B.H; + USE_CYCLES(1) + goto OP_OR; + + OPXY(0xb5): // OR LX + val = data->B.L; + USE_CYCLES(1) + goto OP_OR; + + OPXY(0xb6): // OR (IX+o) + adr = data->W + (INT8)READ_ARG(); + val = READ_MEM8(adr); + USE_CYCLES(11) + goto OP_OR; + +/*----------------------------------------- + MISC ARITHMETIC & CPU CONTROL +-----------------------------------------*/ + + OPXY(0x27): // DAA + goto OP_DAA; + + OPXY(0x2f): // CPL + goto OP_CPL; + + OPXY(0x37): // SCF + goto OP_SCF; + + OPXY(0x3f): // CCF + goto OP_CCF; + + OPXY(0x76): // HALT + goto OP_HALT; + + OPXY(0xf3): // DI + goto OP_DI; + + OPXY(0xfb): // EI + goto OP_EI; + +/*----------------------------------------- + INC r16 +-----------------------------------------*/ + + OPXY(0x03): // INC BC + goto OP_INC_BC; + + OPXY(0x13): // INC DE + goto OP_INC_DE; + + OPXY(0x23): // INC IX + goto OP_INC_xx; + + OPXY(0x33): // INC SP + goto OP_INC_SP; + +/*----------------------------------------- + DEC r16 +-----------------------------------------*/ + + OPXY(0x0b): // DEC BC + goto OP_DEC_BC; + + OPXY(0x1b): // DEC DE + goto OP_DEC_DE; + + OPXY(0x2b): // DEC IX + goto OP_DEC_xx; + + OPXY(0x3b): // DEC SP + goto OP_DEC_SP; + +/*----------------------------------------- + ADD r16 +-----------------------------------------*/ + + OPXY(0x09): // ADD IX,BC + goto OP_ADD16_xx_BC; + + OPXY(0x19): // ADD IX,DE + goto OP_ADD16_xx_DE; + + OPXY(0x29): // ADD IX,IX + goto OP_ADD16_xx_xx; + + OPXY(0x39): // ADD IX,SP + goto OP_ADD16_xx_SP; + +/*----------------------------------------- + ROTATE +-----------------------------------------*/ + + OPXY(0x07): // RLCA + goto OP_RLCA; + + OPXY(0x0f): // RRCA + goto OP_RRCA; + + OPXY(0x17): // RLA + goto OP_RLA; + + OPXY(0x1f): // RRA + goto OP_RRA; + +/*----------------------------------------- + JP +-----------------------------------------*/ + + OPXY(0xc3): // JP nn + goto OP_JP; + + OPXY(0xe9): // JP (IX) + goto OP_JP_xx; + + OPXY(0xc2): // JP NZ,nn + goto OP_JP_NZ; + + OPXY(0xca): // JP Z,nn + goto OP_JP_Z; + + OPXY(0xd2): // JP NC,nn + goto OP_JP_NC; + + OPXY(0xda): // JP C,nn + goto OP_JP_C; + + OPXY(0xe2): // JP PO,nn + goto OP_JP_PO; + + OPXY(0xea): // JP PE,nn + goto OP_JP_PE; + + OPXY(0xf2): // JP P,nn + goto OP_JP_P; + + OPXY(0xfa): // JP M,nn + goto OP_JP_M; + +/*----------------------------------------- + JR +-----------------------------------------*/ + + OPXY(0x10): // DJNZ n + goto OP_DJNZ; + + OPXY(0x18): // JR n + goto OP_JR; + + OPXY(0x20): // JR NZ,n + goto OP_JR_NZ; + + OPXY(0x28): // JR Z,n + goto OP_JR_Z; + + OPXY(0x30): // JR NC,n + goto OP_JR_NC; + + OPXY(0x38): // JR C,n + goto OP_JR_C; + +/*----------------------------------------- + CALL +-----------------------------------------*/ + + OPXY(0xcd): // CALL nn + goto OP_CALL; + + OPXY(0xc4): // CALL NZ,nn + goto OP_CALL_NZ; + + OPXY(0xcc): // CALL Z,nn + goto OP_CALL_Z; + + OPXY(0xd4): // CALL NC,nn + goto OP_CALL_NC; + + OPXY(0xdc): // CALL C,nn + goto OP_CALL_C; + + OPXY(0xe4): // CALL PO,nn + goto OP_CALL_PO; + + OPXY(0xec): // CALL PE,nn + goto OP_CALL_PE; + + OPXY(0xf4): // CALL P,nn + goto OP_CALL_P; + + OPXY(0xfc): // CALL M,nn + goto OP_CALL_M; + +/*----------------------------------------- + RET +-----------------------------------------*/ + + OPXY(0xc9): // RET + goto OP_RET; + + OPXY(0xc0): // RET NZ + goto OP_RET_NZ; + + OPXY(0xc8): // RET Z + goto OP_RET_Z; + + OPXY(0xd0): // RET NC + goto OP_RET_NC; + + OPXY(0xd8): // RET C + goto OP_RET_C; + + OPXY(0xe0): // RET PO + goto OP_RET_PO; + + OPXY(0xe8): // RET PE + goto OP_RET_PE; + + OPXY(0xf0): // RET P + goto OP_RET_P; + + OPXY(0xf8): // RET M + goto OP_RET_M; + +/*----------------------------------------- + RST +-----------------------------------------*/ + + OPXY(0xc7): // RST 0 + OPXY(0xcf): // RST 1 + OPXY(0xd7): // RST 2 + OPXY(0xdf): // RST 3 + OPXY(0xe7): // RST 4 + OPXY(0xef): // RST 5 + OPXY(0xf7): // RST 6 + OPXY(0xff): // RST 7 + goto OP_RST; + +/*----------------------------------------- + OUT +-----------------------------------------*/ + + OPXY(0xd3): // OUT (n),A + goto OP_OUT_mN_A; + +/*----------------------------------------- + IN +-----------------------------------------*/ + + OPXY(0xdb): // IN A,(n) + goto OP_IN_A_mN; + +/*----------------------------------------- + PREFIX +-----------------------------------------*/ + + OPXY(0xcb): // XYCB prefix (BIT & SHIFT INSTRUCTIONS) + { + UINT8 src; + UINT8 res; + + adr = data->W + (INT8)READ_ARG(); + Opcode = READ_ARG(); +#if CZ80_EMULATE_R_EXACTLY + zR++; +#endif + #include "cz80_opXYCB.inc" + } + + OPXY(0xed): // ED prefix + goto ED_PREFIX; + + OPXY(0xdd): // DD prefix (IX) + goto DD_PREFIX; + + OPXY(0xfd): // FD prefix (IY) + goto FD_PREFIX; + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/waterbox/picodrive/cpu/cz80/cz80_opXYCB.inc b/waterbox/picodrive/cpu/cz80/cz80_opXYCB.inc new file mode 100644 index 0000000000..b706580b66 --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80_opXYCB.inc @@ -0,0 +1,474 @@ +/****************************************************************************** + * + * CZ80 XYCB opcode include source file + * CZ80 emulator version 0.9 + * Copyright 2004-2005 Stphane Dallongeville + * + * (Modified by NJ) + * + *****************************************************************************/ + +#if CZ80_USE_JUMPTABLE + goto *JumpTableXYCB[Opcode]; +#else +switch (Opcode) +{ +#endif + +/*----------------------------------------- + RLC +-----------------------------------------*/ + + OPXYCB(0x00): // RLC (Ix+d), B + OPXYCB(0x01): // RLC (Ix+d), C + OPXYCB(0x02): // RLC (Ix+d), D + OPXYCB(0x03): // RLC (Ix+d), E + OPXYCB(0x04): // RLC (Ix+d), H + OPXYCB(0x05): // RLC (Ix+d), L + OPXYCB(0x07): // RLC (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | (src >> 7)) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x06): // RLC (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | (src >> 7)) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RRC +-----------------------------------------*/ + + OPXYCB(0x08): // RRC (Ix+d), B + OPXYCB(0x09): // RRC (Ix+d), C + OPXYCB(0x0a): // RRC (Ix+d), D + OPXYCB(0x0b): // RRC (Ix+d), E + OPXYCB(0x0c): // RRC (Ix+d), H + OPXYCB(0x0d): // RRC (Ix+d), L + OPXYCB(0x0f): // RRC (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (src << 7)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x0e): // RRC (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (src << 7)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RL +-----------------------------------------*/ + + OPXYCB(0x10): // RL (Ix+d), B + OPXYCB(0x11): // RL (Ix+d), C + OPXYCB(0x12): // RL (Ix+d), D + OPXYCB(0x13): // RL (Ix+d), E + OPXYCB(0x14): // RL (Ix+d), H + OPXYCB(0x15): // RL (Ix+d), L + OPXYCB(0x17): // RL (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | (zF & CF)) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x16): // RL (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | (zF & CF)) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + RR +-----------------------------------------*/ + + OPXYCB(0x18): // RR (Ix+d), B + OPXYCB(0x19): // RR (Ix+d), C + OPXYCB(0x1a): // RR (Ix+d), D + OPXYCB(0x1b): // RR (Ix+d), E + OPXYCB(0x1c): // RR (Ix+d), H + OPXYCB(0x1d): // RR (Ix+d), L + OPXYCB(0x1f): // RR (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (zF << 7)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x1e): // RR (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (zF << 7)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SLA +-----------------------------------------*/ + + OPXYCB(0x20): // SLA (Ix+d), B + OPXYCB(0x21): // SLA (Ix+d), C + OPXYCB(0x22): // SLA (Ix+d), D + OPXYCB(0x23): // SLA (Ix+d), E + OPXYCB(0x24): // SLA (Ix+d), H + OPXYCB(0x25): // SLA (Ix+d), L + OPXYCB(0x27): // SLA (Ix+d), A + src = READ_MEM8(adr); + res = (src << 1) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x26): // SLA (Ix+d) + src = READ_MEM8(adr); + res = (src << 1) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SRA +-----------------------------------------*/ + + OPXYCB(0x28): // SRA (Ix+d), B + OPXYCB(0x29): // SRA (Ix+d), C + OPXYCB(0x2a): // SRA (Ix+d), D + OPXYCB(0x2b): // SRA (Ix+d), E + OPXYCB(0x2c): // SRA (Ix+d), H + OPXYCB(0x2d): // SRA (Ix+d), L + OPXYCB(0x2f): // SRA (Ix+d), A + src = READ_MEM8(adr); + res = ((src >> 1) | (src & 0x80)) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x2e): // SRA (Ix+d) + src = READ_MEM8(adr); + res = ((src >> 1) | (src & 0x80)) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SLL +-----------------------------------------*/ + + OPXYCB(0x30): // SLL (Ix+d), B + OPXYCB(0x31): // SLL (Ix+d), C + OPXYCB(0x32): // SLL (Ix+d), D + OPXYCB(0x33): // SLL (Ix+d), E + OPXYCB(0x34): // SLL (Ix+d), H + OPXYCB(0x35): // SLL (Ix+d), L + OPXYCB(0x37): // SLL (Ix+d), A + src = READ_MEM8(adr); + res = ((src << 1) | 0x01) & 0xff; + zF = SZP[res] | (src >> 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x36): // SLL (Ix+d) + src = READ_MEM8(adr); + res = ((src << 1) | 0x01) & 0xff; + zF = SZP[res] | (src >> 7); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SRL +-----------------------------------------*/ + + OPXYCB(0x38): // SRL (Ix+d), B + OPXYCB(0x39): // SRL (Ix+d), C + OPXYCB(0x3a): // SRL (Ix+d), D + OPXYCB(0x3b): // SRL (Ix+d), E + OPXYCB(0x3c): // SRL (Ix+d), H + OPXYCB(0x3d): // SRL (Ix+d), L + OPXYCB(0x3f): // SRL (Ix+d), A + src = READ_MEM8(adr); + res = (src >> 1) & 0xff; + zF = SZP[res] | (src & CF); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x3e): // SRL (Ix+d) + src = READ_MEM8(adr); + res = (src >> 1) & 0xff; + zF = SZP[res] | (src & CF); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + BIT +-----------------------------------------*/ + + OPXYCB(0x40): // BIT 0,(Ix+d) + OPXYCB(0x41): // BIT 0,(Ix+d) + OPXYCB(0x42): // BIT 0,(Ix+d) + OPXYCB(0x43): // BIT 0,(Ix+d) + OPXYCB(0x44): // BIT 0,(Ix+d) + OPXYCB(0x45): // BIT 0,(Ix+d) + OPXYCB(0x47): // BIT 0,(Ix+d) + + OPXYCB(0x48): // BIT 1,(Ix+d) + OPXYCB(0x49): // BIT 1,(Ix+d) + OPXYCB(0x4a): // BIT 1,(Ix+d) + OPXYCB(0x4b): // BIT 1,(Ix+d) + OPXYCB(0x4c): // BIT 1,(Ix+d) + OPXYCB(0x4d): // BIT 1,(Ix+d) + OPXYCB(0x4f): // BIT 1,(Ix+d) + + OPXYCB(0x50): // BIT 2,(Ix+d) + OPXYCB(0x51): // BIT 2,(Ix+d) + OPXYCB(0x52): // BIT 2,(Ix+d) + OPXYCB(0x53): // BIT 2,(Ix+d) + OPXYCB(0x54): // BIT 2,(Ix+d) + OPXYCB(0x55): // BIT 2,(Ix+d) + OPXYCB(0x57): // BIT 2,(Ix+d) + + OPXYCB(0x58): // BIT 3,(Ix+d) + OPXYCB(0x59): // BIT 3,(Ix+d) + OPXYCB(0x5a): // BIT 3,(Ix+d) + OPXYCB(0x5b): // BIT 3,(Ix+d) + OPXYCB(0x5c): // BIT 3,(Ix+d) + OPXYCB(0x5d): // BIT 3,(Ix+d) + OPXYCB(0x5f): // BIT 3,(Ix+d) + + OPXYCB(0x60): // BIT 4,(Ix+d) + OPXYCB(0x61): // BIT 4,(Ix+d) + OPXYCB(0x62): // BIT 4,(Ix+d) + OPXYCB(0x63): // BIT 4,(Ix+d) + OPXYCB(0x64): // BIT 4,(Ix+d) + OPXYCB(0x65): // BIT 4,(Ix+d) + OPXYCB(0x67): // BIT 4,(Ix+d) + + OPXYCB(0x68): // BIT 5,(Ix+d) + OPXYCB(0x69): // BIT 5,(Ix+d) + OPXYCB(0x6a): // BIT 5,(Ix+d) + OPXYCB(0x6b): // BIT 5,(Ix+d) + OPXYCB(0x6c): // BIT 5,(Ix+d) + OPXYCB(0x6d): // BIT 5,(Ix+d) + OPXYCB(0x6f): // BIT 5,(Ix+d) + + OPXYCB(0x70): // BIT 6,(Ix+d) + OPXYCB(0x71): // BIT 6,(Ix+d) + OPXYCB(0x72): // BIT 6,(Ix+d) + OPXYCB(0x73): // BIT 6,(Ix+d) + OPXYCB(0x74): // BIT 6,(Ix+d) + OPXYCB(0x75): // BIT 6,(Ix+d) + OPXYCB(0x77): // BIT 6,(Ix+d) + + OPXYCB(0x78): // BIT 7,(Ix+d) + OPXYCB(0x79): // BIT 7,(Ix+d) + OPXYCB(0x7a): // BIT 7,(Ix+d) + OPXYCB(0x7b): // BIT 7,(Ix+d) + OPXYCB(0x7c): // BIT 7,(Ix+d) + OPXYCB(0x7d): // BIT 7,(Ix+d) + OPXYCB(0x7f): // BIT 7,(Ix+d) + + OPXYCB(0x46): // BIT 0,(Ix+d) + OPXYCB(0x4e): // BIT 1,(Ix+d) + OPXYCB(0x56): // BIT 2,(Ix+d) + OPXYCB(0x5e): // BIT 3,(Ix+d) + OPXYCB(0x66): // BIT 4,(Ix+d) + OPXYCB(0x6e): // BIT 5,(Ix+d) + OPXYCB(0x76): // BIT 6,(Ix+d) + OPXYCB(0x7e): // BIT 7,(Ix+d) + src = READ_MEM8(adr); + zF = (zF & CF) | HF | + (SZ_BIT[src & (1 << ((Opcode >> 3) & 7))] & ~(YF | XF)) | + ((adr >> 8) & (YF | XF)); + RET(16) + +/*----------------------------------------- + RES +-----------------------------------------*/ + + OPXYCB(0x80): // RES 0,(Ix+d),B + OPXYCB(0x81): // RES 0,(Ix+d),C + OPXYCB(0x82): // RES 0,(Ix+d),D + OPXYCB(0x83): // RES 0,(Ix+d),E + OPXYCB(0x84): // RES 0,(Ix+d),H + OPXYCB(0x85): // RES 0,(Ix+d),L + OPXYCB(0x87): // RES 0,(Ix+d),A + + OPXYCB(0x88): // RES 1,(Ix+d),B + OPXYCB(0x89): // RES 1,(Ix+d),C + OPXYCB(0x8a): // RES 1,(Ix+d),D + OPXYCB(0x8b): // RES 1,(Ix+d),E + OPXYCB(0x8c): // RES 1,(Ix+d),H + OPXYCB(0x8d): // RES 1,(Ix+d),L + OPXYCB(0x8f): // RES 1,(Ix+d),A + + OPXYCB(0x90): // RES 2,(Ix+d),B + OPXYCB(0x91): // RES 2,(Ix+d),C + OPXYCB(0x92): // RES 2,(Ix+d),D + OPXYCB(0x93): // RES 2,(Ix+d),E + OPXYCB(0x94): // RES 2,(Ix+d),H + OPXYCB(0x95): // RES 2,(Ix+d),L + OPXYCB(0x97): // RES 2,(Ix+d),A + + OPXYCB(0x98): // RES 3,(Ix+d),B + OPXYCB(0x99): // RES 3,(Ix+d),C + OPXYCB(0x9a): // RES 3,(Ix+d),D + OPXYCB(0x9b): // RES 3,(Ix+d),E + OPXYCB(0x9c): // RES 3,(Ix+d),H + OPXYCB(0x9d): // RES 3,(Ix+d),L + OPXYCB(0x9f): // RES 3,(Ix+d),A + + OPXYCB(0xa0): // RES 4,(Ix+d),B + OPXYCB(0xa1): // RES 4,(Ix+d),C + OPXYCB(0xa2): // RES 4,(Ix+d),D + OPXYCB(0xa3): // RES 4,(Ix+d),E + OPXYCB(0xa4): // RES 4,(Ix+d),H + OPXYCB(0xa5): // RES 4,(Ix+d),L + OPXYCB(0xa7): // RES 4,(Ix+d),A + + OPXYCB(0xa8): // RES 5,(Ix+d),B + OPXYCB(0xa9): // RES 5,(Ix+d),C + OPXYCB(0xaa): // RES 5,(Ix+d),D + OPXYCB(0xab): // RES 5,(Ix+d),E + OPXYCB(0xac): // RES 5,(Ix+d),H + OPXYCB(0xad): // RES 5,(Ix+d),L + OPXYCB(0xaf): // RES 5,(Ix+d),A + + OPXYCB(0xb0): // RES 6,(Ix+d),B + OPXYCB(0xb1): // RES 6,(Ix+d),C + OPXYCB(0xb2): // RES 6,(Ix+d),D + OPXYCB(0xb3): // RES 6,(Ix+d),E + OPXYCB(0xb4): // RES 6,(Ix+d),H + OPXYCB(0xb5): // RES 6,(Ix+d),L + OPXYCB(0xb7): // RES 6,(Ix+d),A + + OPXYCB(0xb8): // RES 7,(Ix+d),B + OPXYCB(0xb9): // RES 7,(Ix+d),C + OPXYCB(0xba): // RES 7,(Ix+d),D + OPXYCB(0xbb): // RES 7,(Ix+d),E + OPXYCB(0xbc): // RES 7,(Ix+d),H + OPXYCB(0xbd): // RES 7,(Ix+d),L + OPXYCB(0xbf): // RES 7,(Ix+d),A + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0x86): // RES 0,(Ix+d) + OPXYCB(0x8e): // RES 1,(Ix+d) + OPXYCB(0x96): // RES 2,(Ix+d) + OPXYCB(0x9e): // RES 3,(Ix+d) + OPXYCB(0xa6): // RES 4,(Ix+d) + OPXYCB(0xae): // RES 5,(Ix+d) + OPXYCB(0xb6): // RES 6,(Ix+d) + OPXYCB(0xbe): // RES 7,(Ix+d) + res = READ_MEM8(adr); + res &= ~(1 << ((Opcode >> 3) & 7)); + WRITE_MEM8(adr, res); + RET(19) + +/*----------------------------------------- + SET +-----------------------------------------*/ + + OPXYCB(0xc0): // SET 0,(Ix+d),B + OPXYCB(0xc1): // SET 0,(Ix+d),C + OPXYCB(0xc2): // SET 0,(Ix+d),D + OPXYCB(0xc3): // SET 0,(Ix+d),E + OPXYCB(0xc4): // SET 0,(Ix+d),H + OPXYCB(0xc5): // SET 0,(Ix+d),L + OPXYCB(0xc7): // SET 0,(Ix+d),A + + OPXYCB(0xc8): // SET 1,(Ix+d),B + OPXYCB(0xc9): // SET 1,(Ix+d),C + OPXYCB(0xca): // SET 1,(Ix+d),D + OPXYCB(0xcb): // SET 1,(Ix+d),E + OPXYCB(0xcc): // SET 1,(Ix+d),H + OPXYCB(0xcd): // SET 1,(Ix+d),L + OPXYCB(0xcf): // SET 1,(Ix+d),A + + OPXYCB(0xd0): // SET 2,(Ix+d),B + OPXYCB(0xd1): // SET 2,(Ix+d),C + OPXYCB(0xd2): // SET 2,(Ix+d),D + OPXYCB(0xd3): // SET 2,(Ix+d),E + OPXYCB(0xd4): // SET 2,(Ix+d),H + OPXYCB(0xd5): // SET 2,(Ix+d),L + OPXYCB(0xd7): // SET 2,(Ix+d),A + + OPXYCB(0xd8): // SET 3,(Ix+d),B + OPXYCB(0xd9): // SET 3,(Ix+d),C + OPXYCB(0xda): // SET 3,(Ix+d),D + OPXYCB(0xdb): // SET 3,(Ix+d),E + OPXYCB(0xdc): // SET 3,(Ix+d),H + OPXYCB(0xdd): // SET 3,(Ix+d),L + OPXYCB(0xdf): // SET 3,(Ix+d),A + + OPXYCB(0xe0): // SET 4,(Ix+d),B + OPXYCB(0xe1): // SET 4,(Ix+d),C + OPXYCB(0xe2): // SET 4,(Ix+d),D + OPXYCB(0xe3): // SET 4,(Ix+d),E + OPXYCB(0xe4): // SET 4,(Ix+d),H + OPXYCB(0xe5): // SET 4,(Ix+d),L + OPXYCB(0xe7): // SET 4,(Ix+d),A + + OPXYCB(0xe8): // SET 5,(Ix+d),B + OPXYCB(0xe9): // SET 5,(Ix+d),C + OPXYCB(0xea): // SET 5,(Ix+d),D + OPXYCB(0xeb): // SET 5,(Ix+d),E + OPXYCB(0xec): // SET 5,(Ix+d),H + OPXYCB(0xed): // SET 5,(Ix+d),L + OPXYCB(0xef): // SET 5,(Ix+d),A + + OPXYCB(0xf0): // SET 6,(Ix+d),B + OPXYCB(0xf1): // SET 6,(Ix+d),C + OPXYCB(0xf2): // SET 6,(Ix+d),D + OPXYCB(0xf3): // SET 6,(Ix+d),E + OPXYCB(0xf4): // SET 6,(Ix+d),H + OPXYCB(0xf5): // SET 6,(Ix+d),L + OPXYCB(0xf7): // SET 6,(Ix+d),A + + OPXYCB(0xf8): // SET 7,(Ix+d),B + OPXYCB(0xf9): // SET 7,(Ix+d),C + OPXYCB(0xfa): // SET 7,(Ix+d),D + OPXYCB(0xfb): // SET 7,(Ix+d),E + OPXYCB(0xfc): // SET 7,(Ix+d),H + OPXYCB(0xfd): // SET 7,(Ix+d),L + OPXYCB(0xff): // SET 7,(Ix+d),A + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + zR8(Opcode & 7) = res; + WRITE_MEM8(adr, res); + RET(19) + + OPXYCB(0xc6): // SET 0,(Ix+d) + OPXYCB(0xce): // SET 1,(Ix+d) + OPXYCB(0xd6): // SET 2,(Ix+d) + OPXYCB(0xde): // SET 3,(Ix+d) + OPXYCB(0xe6): // SET 4,(Ix+d) + OPXYCB(0xee): // SET 5,(Ix+d) + OPXYCB(0xf6): // SET 6,(Ix+d) + OPXYCB(0xfe): // SET 7,(Ix+d) + res = READ_MEM8(adr); + res |= 1 << ((Opcode >> 3) & 7); + WRITE_MEM8(adr, res); + RET(19) + +#if !CZ80_USE_JUMPTABLE +} +#endif diff --git a/waterbox/picodrive/cpu/cz80/cz80jmp.inc b/waterbox/picodrive/cpu/cz80/cz80jmp.inc new file mode 100644 index 0000000000..0100772226 --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80jmp.inc @@ -0,0 +1,422 @@ +/****************************************************************************** + + cz80jmp.c + + CZ80 opcodeWve[u + +******************************************************************************/ + +static const void ALIGN_DATA *JumpTable[0x100] = +{ + &&OP0x00, &&OP0x01, &&OP0x02, &&OP0x03, + &&OP0x04, &&OP0x05, &&OP0x06, &&OP0x07, + &&OP0x08, &&OP0x09, &&OP0x0a, &&OP0x0b, + &&OP0x0c, &&OP0x0d, &&OP0x0e, &&OP0x0f, + + &&OP0x10, &&OP0x11, &&OP0x12, &&OP0x13, + &&OP0x14, &&OP0x15, &&OP0x16, &&OP0x17, + &&OP0x18, &&OP0x19, &&OP0x1a, &&OP0x1b, + &&OP0x1c, &&OP0x1d, &&OP0x1e, &&OP0x1f, + + &&OP0x20, &&OP0x21, &&OP0x22, &&OP0x23, + &&OP0x24, &&OP0x25, &&OP0x26, &&OP0x27, + &&OP0x28, &&OP0x29, &&OP0x2a, &&OP0x2b, + &&OP0x2c, &&OP0x2d, &&OP0x2e, &&OP0x2f, + + &&OP0x30, &&OP0x31, &&OP0x32, &&OP0x33, + &&OP0x34, &&OP0x35, &&OP0x36, &&OP0x37, + &&OP0x38, &&OP0x39, &&OP0x3a, &&OP0x3b, + &&OP0x3c, &&OP0x3d, &&OP0x3e, &&OP0x3f, + + &&OP0x40, &&OP0x41, &&OP0x42, &&OP0x43, + &&OP0x44, &&OP0x45, &&OP0x46, &&OP0x47, + &&OP0x48, &&OP0x49, &&OP0x4a, &&OP0x4b, + &&OP0x4c, &&OP0x4d, &&OP0x4e, &&OP0x4f, + + &&OP0x50, &&OP0x51, &&OP0x52, &&OP0x53, + &&OP0x54, &&OP0x55, &&OP0x56, &&OP0x57, + &&OP0x58, &&OP0x59, &&OP0x5a, &&OP0x5b, + &&OP0x5c, &&OP0x5d, &&OP0x5e, &&OP0x5f, + + &&OP0x60, &&OP0x61, &&OP0x62, &&OP0x63, + &&OP0x64, &&OP0x65, &&OP0x66, &&OP0x67, + &&OP0x68, &&OP0x69, &&OP0x6a, &&OP0x6b, + &&OP0x6c, &&OP0x6d, &&OP0x6e, &&OP0x6f, + + &&OP0x70, &&OP0x71, &&OP0x72, &&OP0x73, + &&OP0x74, &&OP0x75, &&OP0x76, &&OP0x77, + &&OP0x78, &&OP0x79, &&OP0x7a, &&OP0x7b, + &&OP0x7c, &&OP0x7d, &&OP0x7e, &&OP0x7f, + + &&OP0x80, &&OP0x81, &&OP0x82, &&OP0x83, + &&OP0x84, &&OP0x85, &&OP0x86, &&OP0x87, + &&OP0x88, &&OP0x89, &&OP0x8a, &&OP0x8b, + &&OP0x8c, &&OP0x8d, &&OP0x8e, &&OP0x8f, + + &&OP0x90, &&OP0x91, &&OP0x92, &&OP0x93, + &&OP0x94, &&OP0x95, &&OP0x96, &&OP0x97, + &&OP0x98, &&OP0x99, &&OP0x9a, &&OP0x9b, + &&OP0x9c, &&OP0x9d, &&OP0x9e, &&OP0x9f, + + &&OP0xa0, &&OP0xa1, &&OP0xa2, &&OP0xa3, + &&OP0xa4, &&OP0xa5, &&OP0xa6, &&OP0xa7, + &&OP0xa8, &&OP0xa9, &&OP0xaa, &&OP0xab, + &&OP0xac, &&OP0xad, &&OP0xae, &&OP0xaf, + + &&OP0xb0, &&OP0xb1, &&OP0xb2, &&OP0xb3, + &&OP0xb4, &&OP0xb5, &&OP0xb6, &&OP0xb7, + &&OP0xb8, &&OP0xb9, &&OP0xba, &&OP0xbb, + &&OP0xbc, &&OP0xbd, &&OP0xbe, &&OP0xbf, + + &&OP0xc0, &&OP0xc1, &&OP0xc2, &&OP0xc3, + &&OP0xc4, &&OP0xc5, &&OP0xc6, &&OP0xc7, + &&OP0xc8, &&OP0xc9, &&OP0xca, &&OP0xcb, + &&OP0xcc, &&OP0xcd, &&OP0xce, &&OP0xcf, + + &&OP0xd0, &&OP0xd1, &&OP0xd2, &&OP0xd3, + &&OP0xd4, &&OP0xd5, &&OP0xd6, &&OP0xd7, + &&OP0xd8, &&OP0xd9, &&OP0xda, &&OP0xdb, + &&OP0xdc, &&OP0xdd, &&OP0xde, &&OP0xdf, + + &&OP0xe0, &&OP0xe1, &&OP0xe2, &&OP0xe3, + &&OP0xe4, &&OP0xe5, &&OP0xe6, &&OP0xe7, + &&OP0xe8, &&OP0xe9, &&OP0xea, &&OP0xeb, + &&OP0xec, &&OP0xed, &&OP0xee, &&OP0xef, + + &&OP0xf0, &&OP0xf1, &&OP0xf2, &&OP0xf3, + &&OP0xf4, &&OP0xf5, &&OP0xf6, &&OP0xf7, + &&OP0xf8, &&OP0xf9, &&OP0xfa, &&OP0xfb, + &&OP0xfc, &&OP0xfd, &&OP0xfe, &&OP0xff +}; + +static const void ALIGN_DATA *JumpTableCB[0x100] = +{ + &&OPCB0x00, &&OPCB0x01, &&OPCB0x02, &&OPCB0x03, + &&OPCB0x04, &&OPCB0x05, &&OPCB0x06, &&OPCB0x07, + &&OPCB0x08, &&OPCB0x09, &&OPCB0x0a, &&OPCB0x0b, + &&OPCB0x0c, &&OPCB0x0d, &&OPCB0x0e, &&OPCB0x0f, + + &&OPCB0x10, &&OPCB0x11, &&OPCB0x12, &&OPCB0x13, + &&OPCB0x14, &&OPCB0x15, &&OPCB0x16, &&OPCB0x17, + &&OPCB0x18, &&OPCB0x19, &&OPCB0x1a, &&OPCB0x1b, + &&OPCB0x1c, &&OPCB0x1d, &&OPCB0x1e, &&OPCB0x1f, + + &&OPCB0x20, &&OPCB0x21, &&OPCB0x22, &&OPCB0x23, + &&OPCB0x24, &&OPCB0x25, &&OPCB0x26, &&OPCB0x27, + &&OPCB0x28, &&OPCB0x29, &&OPCB0x2a, &&OPCB0x2b, + &&OPCB0x2c, &&OPCB0x2d, &&OPCB0x2e, &&OPCB0x2f, + + &&OPCB0x30, &&OPCB0x31, &&OPCB0x32, &&OPCB0x33, + &&OPCB0x34, &&OPCB0x35, &&OPCB0x36, &&OPCB0x37, + &&OPCB0x38, &&OPCB0x39, &&OPCB0x3a, &&OPCB0x3b, + &&OPCB0x3c, &&OPCB0x3d, &&OPCB0x3e, &&OPCB0x3f, + + &&OPCB0x40, &&OPCB0x41, &&OPCB0x42, &&OPCB0x43, + &&OPCB0x44, &&OPCB0x45, &&OPCB0x46, &&OPCB0x47, + &&OPCB0x48, &&OPCB0x49, &&OPCB0x4a, &&OPCB0x4b, + &&OPCB0x4c, &&OPCB0x4d, &&OPCB0x4e, &&OPCB0x4f, + + &&OPCB0x50, &&OPCB0x51, &&OPCB0x52, &&OPCB0x53, + &&OPCB0x54, &&OPCB0x55, &&OPCB0x56, &&OPCB0x57, + &&OPCB0x58, &&OPCB0x59, &&OPCB0x5a, &&OPCB0x5b, + &&OPCB0x5c, &&OPCB0x5d, &&OPCB0x5e, &&OPCB0x5f, + + &&OPCB0x60, &&OPCB0x61, &&OPCB0x62, &&OPCB0x63, + &&OPCB0x64, &&OPCB0x65, &&OPCB0x66, &&OPCB0x67, + &&OPCB0x68, &&OPCB0x69, &&OPCB0x6a, &&OPCB0x6b, + &&OPCB0x6c, &&OPCB0x6d, &&OPCB0x6e, &&OPCB0x6f, + + &&OPCB0x70, &&OPCB0x71, &&OPCB0x72, &&OPCB0x73, + &&OPCB0x74, &&OPCB0x75, &&OPCB0x76, &&OPCB0x77, + &&OPCB0x78, &&OPCB0x79, &&OPCB0x7a, &&OPCB0x7b, + &&OPCB0x7c, &&OPCB0x7d, &&OPCB0x7e, &&OPCB0x7f, + + &&OPCB0x80, &&OPCB0x81, &&OPCB0x82, &&OPCB0x83, + &&OPCB0x84, &&OPCB0x85, &&OPCB0x86, &&OPCB0x87, + &&OPCB0x88, &&OPCB0x89, &&OPCB0x8a, &&OPCB0x8b, + &&OPCB0x8c, &&OPCB0x8d, &&OPCB0x8e, &&OPCB0x8f, + + &&OPCB0x90, &&OPCB0x91, &&OPCB0x92, &&OPCB0x93, + &&OPCB0x94, &&OPCB0x95, &&OPCB0x96, &&OPCB0x97, + &&OPCB0x98, &&OPCB0x99, &&OPCB0x9a, &&OPCB0x9b, + &&OPCB0x9c, &&OPCB0x9d, &&OPCB0x9e, &&OPCB0x9f, + + &&OPCB0xa0, &&OPCB0xa1, &&OPCB0xa2, &&OPCB0xa3, + &&OPCB0xa4, &&OPCB0xa5, &&OPCB0xa6, &&OPCB0xa7, + &&OPCB0xa8, &&OPCB0xa9, &&OPCB0xaa, &&OPCB0xab, + &&OPCB0xac, &&OPCB0xad, &&OPCB0xae, &&OPCB0xaf, + + &&OPCB0xb0, &&OPCB0xb1, &&OPCB0xb2, &&OPCB0xb3, + &&OPCB0xb4, &&OPCB0xb5, &&OPCB0xb6, &&OPCB0xb7, + &&OPCB0xb8, &&OPCB0xb9, &&OPCB0xba, &&OPCB0xbb, + &&OPCB0xbc, &&OPCB0xbd, &&OPCB0xbe, &&OPCB0xbf, + + &&OPCB0xc0, &&OPCB0xc1, &&OPCB0xc2, &&OPCB0xc3, + &&OPCB0xc4, &&OPCB0xc5, &&OPCB0xc6, &&OPCB0xc7, + &&OPCB0xc8, &&OPCB0xc9, &&OPCB0xca, &&OPCB0xcb, + &&OPCB0xcc, &&OPCB0xcd, &&OPCB0xce, &&OPCB0xcf, + + &&OPCB0xd0, &&OPCB0xd1, &&OPCB0xd2, &&OPCB0xd3, + &&OPCB0xd4, &&OPCB0xd5, &&OPCB0xd6, &&OPCB0xd7, + &&OPCB0xd8, &&OPCB0xd9, &&OPCB0xda, &&OPCB0xdb, + &&OPCB0xdc, &&OPCB0xdd, &&OPCB0xde, &&OPCB0xdf, + + &&OPCB0xe0, &&OPCB0xe1, &&OPCB0xe2, &&OPCB0xe3, + &&OPCB0xe4, &&OPCB0xe5, &&OPCB0xe6, &&OPCB0xe7, + &&OPCB0xe8, &&OPCB0xe9, &&OPCB0xea, &&OPCB0xeb, + &&OPCB0xec, &&OPCB0xed, &&OPCB0xee, &&OPCB0xef, + + &&OPCB0xf0, &&OPCB0xf1, &&OPCB0xf2, &&OPCB0xf3, + &&OPCB0xf4, &&OPCB0xf5, &&OPCB0xf6, &&OPCB0xf7, + &&OPCB0xf8, &&OPCB0xf9, &&OPCB0xfa, &&OPCB0xfb, + &&OPCB0xfc, &&OPCB0xfd, &&OPCB0xfe, &&OPCB0xff +}; + +static const void ALIGN_DATA *JumpTableED[0x100] = +{ + &&OPED0x00, &&OPED0x01, &&OPED0x02, &&OPED0x03, + &&OPED0x04, &&OPED0x05, &&OPED0x06, &&OPED0x07, + &&OPED0x08, &&OPED0x09, &&OPED0x0a, &&OPED0x0b, + &&OPED0x0c, &&OPED0x0d, &&OPED0x0e, &&OPED0x0f, + + &&OPED0x10, &&OPED0x11, &&OPED0x12, &&OPED0x13, + &&OPED0x14, &&OPED0x15, &&OPED0x16, &&OPED0x17, + &&OPED0x18, &&OPED0x19, &&OPED0x1a, &&OPED0x1b, + &&OPED0x1c, &&OPED0x1d, &&OPED0x1e, &&OPED0x1f, + + &&OPED0x20, &&OPED0x21, &&OPED0x22, &&OPED0x23, + &&OPED0x24, &&OPED0x25, &&OPED0x26, &&OPED0x27, + &&OPED0x28, &&OPED0x29, &&OPED0x2a, &&OPED0x2b, + &&OPED0x2c, &&OPED0x2d, &&OPED0x2e, &&OPED0x2f, + + &&OPED0x30, &&OPED0x31, &&OPED0x32, &&OPED0x33, + &&OPED0x34, &&OPED0x35, &&OPED0x36, &&OPED0x37, + &&OPED0x38, &&OPED0x39, &&OPED0x3a, &&OPED0x3b, + &&OPED0x3c, &&OPED0x3d, &&OPED0x3e, &&OPED0x3f, + + &&OPED0x40, &&OPED0x41, &&OPED0x42, &&OPED0x43, + &&OPED0x44, &&OPED0x45, &&OPED0x46, &&OPED0x47, + &&OPED0x48, &&OPED0x49, &&OPED0x4a, &&OPED0x4b, + &&OPED0x4c, &&OPED0x4d, &&OPED0x4e, &&OPED0x4f, + + &&OPED0x50, &&OPED0x51, &&OPED0x52, &&OPED0x53, + &&OPED0x54, &&OPED0x55, &&OPED0x56, &&OPED0x57, + &&OPED0x58, &&OPED0x59, &&OPED0x5a, &&OPED0x5b, + &&OPED0x5c, &&OPED0x5d, &&OPED0x5e, &&OPED0x5f, + + &&OPED0x60, &&OPED0x61, &&OPED0x62, &&OPED0x63, + &&OPED0x64, &&OPED0x65, &&OPED0x66, &&OPED0x67, + &&OPED0x68, &&OPED0x69, &&OPED0x6a, &&OPED0x6b, + &&OPED0x6c, &&OPED0x6d, &&OPED0x6e, &&OPED0x6f, + + &&OPED0x70, &&OPED0x71, &&OPED0x72, &&OPED0x73, + &&OPED0x74, &&OPED0x75, &&OPED0x76, &&OPED0x77, + &&OPED0x78, &&OPED0x79, &&OPED0x7a, &&OPED0x7b, + &&OPED0x7c, &&OPED0x7d, &&OPED0x7e, &&OPED0x7f, + + &&OPED0x80, &&OPED0x81, &&OPED0x82, &&OPED0x83, + &&OPED0x84, &&OPED0x85, &&OPED0x86, &&OPED0x87, + &&OPED0x88, &&OPED0x89, &&OPED0x8a, &&OPED0x8b, + &&OPED0x8c, &&OPED0x8d, &&OPED0x8e, &&OPED0x8f, + + &&OPED0x90, &&OPED0x91, &&OPED0x92, &&OPED0x93, + &&OPED0x94, &&OPED0x95, &&OPED0x96, &&OPED0x97, + &&OPED0x98, &&OPED0x99, &&OPED0x9a, &&OPED0x9b, + &&OPED0x9c, &&OPED0x9d, &&OPED0x9e, &&OPED0x9f, + + &&OPED0xa0, &&OPED0xa1, &&OPED0xa2, &&OPED0xa3, + &&OPED0xa4, &&OPED0xa5, &&OPED0xa6, &&OPED0xa7, + &&OPED0xa8, &&OPED0xa9, &&OPED0xaa, &&OPED0xab, + &&OPED0xac, &&OPED0xad, &&OPED0xae, &&OPED0xaf, + + &&OPED0xb0, &&OPED0xb1, &&OPED0xb2, &&OPED0xb3, + &&OPED0xb4, &&OPED0xb5, &&OPED0xb6, &&OPED0xb7, + &&OPED0xb8, &&OPED0xb9, &&OPED0xba, &&OPED0xbb, + &&OPED0xbc, &&OPED0xbd, &&OPED0xbe, &&OPED0xbf, + + &&OPED0xc0, &&OPED0xc1, &&OPED0xc2, &&OPED0xc3, + &&OPED0xc4, &&OPED0xc5, &&OPED0xc6, &&OPED0xc7, + &&OPED0xc8, &&OPED0xc9, &&OPED0xca, &&OPED0xcb, + &&OPED0xcc, &&OPED0xcd, &&OPED0xce, &&OPED0xcf, + + &&OPED0xd0, &&OPED0xd1, &&OPED0xd2, &&OPED0xd3, + &&OPED0xd4, &&OPED0xd5, &&OPED0xd6, &&OPED0xd7, + &&OPED0xd8, &&OPED0xd9, &&OPED0xda, &&OPED0xdb, + &&OPED0xdc, &&OPED0xdd, &&OPED0xde, &&OPED0xdf, + + &&OPED0xe0, &&OPED0xe1, &&OPED0xe2, &&OPED0xe3, + &&OPED0xe4, &&OPED0xe5, &&OPED0xe6, &&OPED0xe7, + &&OPED0xe8, &&OPED0xe9, &&OPED0xea, &&OPED0xeb, + &&OPED0xec, &&OPED0xed, &&OPED0xee, &&OPED0xef, + + &&OPED0xf0, &&OPED0xf1, &&OPED0xf2, &&OPED0xf3, + &&OPED0xf4, &&OPED0xf5, &&OPED0xf6, &&OPED0xf7, + &&OPED0xf8, &&OPED0xf9, &&OPED0xfa, &&OPED0xfb, + &&OPED0xfc, &&OPED0xfd, &&OPED0xfe, &&OPED0xff +}; + +static const void ALIGN_DATA *JumpTableXY[0x100] = +{ + &&OPXY0x00, &&OPXY0x01, &&OPXY0x02, &&OPXY0x03, + &&OPXY0x04, &&OPXY0x05, &&OPXY0x06, &&OPXY0x07, + &&OPXY0x08, &&OPXY0x09, &&OPXY0x0a, &&OPXY0x0b, + &&OPXY0x0c, &&OPXY0x0d, &&OPXY0x0e, &&OPXY0x0f, + + &&OPXY0x10, &&OPXY0x11, &&OPXY0x12, &&OPXY0x13, + &&OPXY0x14, &&OPXY0x15, &&OPXY0x16, &&OPXY0x17, + &&OPXY0x18, &&OPXY0x19, &&OPXY0x1a, &&OPXY0x1b, + &&OPXY0x1c, &&OPXY0x1d, &&OPXY0x1e, &&OPXY0x1f, + + &&OPXY0x20, &&OPXY0x21, &&OPXY0x22, &&OPXY0x23, + &&OPXY0x24, &&OPXY0x25, &&OPXY0x26, &&OPXY0x27, + &&OPXY0x28, &&OPXY0x29, &&OPXY0x2a, &&OPXY0x2b, + &&OPXY0x2c, &&OPXY0x2d, &&OPXY0x2e, &&OPXY0x2f, + + &&OPXY0x30, &&OPXY0x31, &&OPXY0x32, &&OPXY0x33, + &&OPXY0x34, &&OPXY0x35, &&OPXY0x36, &&OPXY0x37, + &&OPXY0x38, &&OPXY0x39, &&OPXY0x3a, &&OPXY0x3b, + &&OPXY0x3c, &&OPXY0x3d, &&OPXY0x3e, &&OPXY0x3f, + + &&OPXY0x40, &&OPXY0x41, &&OPXY0x42, &&OPXY0x43, + &&OPXY0x44, &&OPXY0x45, &&OPXY0x46, &&OPXY0x47, + &&OPXY0x48, &&OPXY0x49, &&OPXY0x4a, &&OPXY0x4b, + &&OPXY0x4c, &&OPXY0x4d, &&OPXY0x4e, &&OPXY0x4f, + + &&OPXY0x50, &&OPXY0x51, &&OPXY0x52, &&OPXY0x53, + &&OPXY0x54, &&OPXY0x55, &&OPXY0x56, &&OPXY0x57, + &&OPXY0x58, &&OPXY0x59, &&OPXY0x5a, &&OPXY0x5b, + &&OPXY0x5c, &&OPXY0x5d, &&OPXY0x5e, &&OPXY0x5f, + + &&OPXY0x60, &&OPXY0x61, &&OPXY0x62, &&OPXY0x63, + &&OPXY0x64, &&OPXY0x65, &&OPXY0x66, &&OPXY0x67, + &&OPXY0x68, &&OPXY0x69, &&OPXY0x6a, &&OPXY0x6b, + &&OPXY0x6c, &&OPXY0x6d, &&OPXY0x6e, &&OPXY0x6f, + + &&OPXY0x70, &&OPXY0x71, &&OPXY0x72, &&OPXY0x73, + &&OPXY0x74, &&OPXY0x75, &&OPXY0x76, &&OPXY0x77, + &&OPXY0x78, &&OPXY0x79, &&OPXY0x7a, &&OPXY0x7b, + &&OPXY0x7c, &&OPXY0x7d, &&OPXY0x7e, &&OPXY0x7f, + + &&OPXY0x80, &&OPXY0x81, &&OPXY0x82, &&OPXY0x83, + &&OPXY0x84, &&OPXY0x85, &&OPXY0x86, &&OPXY0x87, + &&OPXY0x88, &&OPXY0x89, &&OPXY0x8a, &&OPXY0x8b, + &&OPXY0x8c, &&OPXY0x8d, &&OPXY0x8e, &&OPXY0x8f, + + &&OPXY0x90, &&OPXY0x91, &&OPXY0x92, &&OPXY0x93, + &&OPXY0x94, &&OPXY0x95, &&OPXY0x96, &&OPXY0x97, + &&OPXY0x98, &&OPXY0x99, &&OPXY0x9a, &&OPXY0x9b, + &&OPXY0x9c, &&OPXY0x9d, &&OPXY0x9e, &&OPXY0x9f, + + &&OPXY0xa0, &&OPXY0xa1, &&OPXY0xa2, &&OPXY0xa3, + &&OPXY0xa4, &&OPXY0xa5, &&OPXY0xa6, &&OPXY0xa7, + &&OPXY0xa8, &&OPXY0xa9, &&OPXY0xaa, &&OPXY0xab, + &&OPXY0xac, &&OPXY0xad, &&OPXY0xae, &&OPXY0xaf, + + &&OPXY0xb0, &&OPXY0xb1, &&OPXY0xb2, &&OPXY0xb3, + &&OPXY0xb4, &&OPXY0xb5, &&OPXY0xb6, &&OPXY0xb7, + &&OPXY0xb8, &&OPXY0xb9, &&OPXY0xba, &&OPXY0xbb, + &&OPXY0xbc, &&OPXY0xbd, &&OPXY0xbe, &&OPXY0xbf, + + &&OPXY0xc0, &&OPXY0xc1, &&OPXY0xc2, &&OPXY0xc3, + &&OPXY0xc4, &&OPXY0xc5, &&OPXY0xc6, &&OPXY0xc7, + &&OPXY0xc8, &&OPXY0xc9, &&OPXY0xca, &&OPXY0xcb, + &&OPXY0xcc, &&OPXY0xcd, &&OPXY0xce, &&OPXY0xcf, + + &&OPXY0xd0, &&OPXY0xd1, &&OPXY0xd2, &&OPXY0xd3, + &&OPXY0xd4, &&OPXY0xd5, &&OPXY0xd6, &&OPXY0xd7, + &&OPXY0xd8, &&OPXY0xd9, &&OPXY0xda, &&OPXY0xdb, + &&OPXY0xdc, &&OPXY0xdd, &&OPXY0xde, &&OPXY0xdf, + + &&OPXY0xe0, &&OPXY0xe1, &&OPXY0xe2, &&OPXY0xe3, + &&OPXY0xe4, &&OPXY0xe5, &&OPXY0xe6, &&OPXY0xe7, + &&OPXY0xe8, &&OPXY0xe9, &&OPXY0xea, &&OPXY0xeb, + &&OPXY0xec, &&OPXY0xed, &&OPXY0xee, &&OPXY0xef, + + &&OPXY0xf0, &&OPXY0xf1, &&OPXY0xf2, &&OPXY0xf3, + &&OPXY0xf4, &&OPXY0xf5, &&OPXY0xf6, &&OPXY0xf7, + &&OPXY0xf8, &&OPXY0xf9, &&OPXY0xfa, &&OPXY0xfb, + &&OPXY0xfc, &&OPXY0xfd, &&OPXY0xfe, &&OPXY0xff +}; + +static const void ALIGN_DATA *JumpTableXYCB[0x100] = +{ + &&OPXYCB0x00, &&OPXYCB0x01, &&OPXYCB0x02, &&OPXYCB0x03, + &&OPXYCB0x04, &&OPXYCB0x05, &&OPXYCB0x06, &&OPXYCB0x07, + &&OPXYCB0x08, &&OPXYCB0x09, &&OPXYCB0x0a, &&OPXYCB0x0b, + &&OPXYCB0x0c, &&OPXYCB0x0d, &&OPXYCB0x0e, &&OPXYCB0x0f, + + &&OPXYCB0x10, &&OPXYCB0x11, &&OPXYCB0x12, &&OPXYCB0x13, + &&OPXYCB0x14, &&OPXYCB0x15, &&OPXYCB0x16, &&OPXYCB0x17, + &&OPXYCB0x18, &&OPXYCB0x19, &&OPXYCB0x1a, &&OPXYCB0x1b, + &&OPXYCB0x1c, &&OPXYCB0x1d, &&OPXYCB0x1e, &&OPXYCB0x1f, + + &&OPXYCB0x20, &&OPXYCB0x21, &&OPXYCB0x22, &&OPXYCB0x23, + &&OPXYCB0x24, &&OPXYCB0x25, &&OPXYCB0x26, &&OPXYCB0x27, + &&OPXYCB0x28, &&OPXYCB0x29, &&OPXYCB0x2a, &&OPXYCB0x2b, + &&OPXYCB0x2c, &&OPXYCB0x2d, &&OPXYCB0x2e, &&OPXYCB0x2f, + + &&OPXYCB0x30, &&OPXYCB0x31, &&OPXYCB0x32, &&OPXYCB0x33, + &&OPXYCB0x34, &&OPXYCB0x35, &&OPXYCB0x36, &&OPXYCB0x37, + &&OPXYCB0x38, &&OPXYCB0x39, &&OPXYCB0x3a, &&OPXYCB0x3b, + &&OPXYCB0x3c, &&OPXYCB0x3d, &&OPXYCB0x3e, &&OPXYCB0x3f, + + &&OPXYCB0x40, &&OPXYCB0x41, &&OPXYCB0x42, &&OPXYCB0x43, + &&OPXYCB0x44, &&OPXYCB0x45, &&OPXYCB0x46, &&OPXYCB0x47, + &&OPXYCB0x48, &&OPXYCB0x49, &&OPXYCB0x4a, &&OPXYCB0x4b, + &&OPXYCB0x4c, &&OPXYCB0x4d, &&OPXYCB0x4e, &&OPXYCB0x4f, + + &&OPXYCB0x50, &&OPXYCB0x51, &&OPXYCB0x52, &&OPXYCB0x53, + &&OPXYCB0x54, &&OPXYCB0x55, &&OPXYCB0x56, &&OPXYCB0x57, + &&OPXYCB0x58, &&OPXYCB0x59, &&OPXYCB0x5a, &&OPXYCB0x5b, + &&OPXYCB0x5c, &&OPXYCB0x5d, &&OPXYCB0x5e, &&OPXYCB0x5f, + + &&OPXYCB0x60, &&OPXYCB0x61, &&OPXYCB0x62, &&OPXYCB0x63, + &&OPXYCB0x64, &&OPXYCB0x65, &&OPXYCB0x66, &&OPXYCB0x67, + &&OPXYCB0x68, &&OPXYCB0x69, &&OPXYCB0x6a, &&OPXYCB0x6b, + &&OPXYCB0x6c, &&OPXYCB0x6d, &&OPXYCB0x6e, &&OPXYCB0x6f, + + &&OPXYCB0x70, &&OPXYCB0x71, &&OPXYCB0x72, &&OPXYCB0x73, + &&OPXYCB0x74, &&OPXYCB0x75, &&OPXYCB0x76, &&OPXYCB0x77, + &&OPXYCB0x78, &&OPXYCB0x79, &&OPXYCB0x7a, &&OPXYCB0x7b, + &&OPXYCB0x7c, &&OPXYCB0x7d, &&OPXYCB0x7e, &&OPXYCB0x7f, + + &&OPXYCB0x80, &&OPXYCB0x81, &&OPXYCB0x82, &&OPXYCB0x83, + &&OPXYCB0x84, &&OPXYCB0x85, &&OPXYCB0x86, &&OPXYCB0x87, + &&OPXYCB0x88, &&OPXYCB0x89, &&OPXYCB0x8a, &&OPXYCB0x8b, + &&OPXYCB0x8c, &&OPXYCB0x8d, &&OPXYCB0x8e, &&OPXYCB0x8f, + + &&OPXYCB0x90, &&OPXYCB0x91, &&OPXYCB0x92, &&OPXYCB0x93, + &&OPXYCB0x94, &&OPXYCB0x95, &&OPXYCB0x96, &&OPXYCB0x97, + &&OPXYCB0x98, &&OPXYCB0x99, &&OPXYCB0x9a, &&OPXYCB0x9b, + &&OPXYCB0x9c, &&OPXYCB0x9d, &&OPXYCB0x9e, &&OPXYCB0x9f, + + &&OPXYCB0xa0, &&OPXYCB0xa1, &&OPXYCB0xa2, &&OPXYCB0xa3, + &&OPXYCB0xa4, &&OPXYCB0xa5, &&OPXYCB0xa6, &&OPXYCB0xa7, + &&OPXYCB0xa8, &&OPXYCB0xa9, &&OPXYCB0xaa, &&OPXYCB0xab, + &&OPXYCB0xac, &&OPXYCB0xad, &&OPXYCB0xae, &&OPXYCB0xaf, + + &&OPXYCB0xb0, &&OPXYCB0xb1, &&OPXYCB0xb2, &&OPXYCB0xb3, + &&OPXYCB0xb4, &&OPXYCB0xb5, &&OPXYCB0xb6, &&OPXYCB0xb7, + &&OPXYCB0xb8, &&OPXYCB0xb9, &&OPXYCB0xba, &&OPXYCB0xbb, + &&OPXYCB0xbc, &&OPXYCB0xbd, &&OPXYCB0xbe, &&OPXYCB0xbf, + + &&OPXYCB0xc0, &&OPXYCB0xc1, &&OPXYCB0xc2, &&OPXYCB0xc3, + &&OPXYCB0xc4, &&OPXYCB0xc5, &&OPXYCB0xc6, &&OPXYCB0xc7, + &&OPXYCB0xc8, &&OPXYCB0xc9, &&OPXYCB0xca, &&OPXYCB0xcb, + &&OPXYCB0xcc, &&OPXYCB0xcd, &&OPXYCB0xce, &&OPXYCB0xcf, + + &&OPXYCB0xd0, &&OPXYCB0xd1, &&OPXYCB0xd2, &&OPXYCB0xd3, + &&OPXYCB0xd4, &&OPXYCB0xd5, &&OPXYCB0xd6, &&OPXYCB0xd7, + &&OPXYCB0xd8, &&OPXYCB0xd9, &&OPXYCB0xda, &&OPXYCB0xdb, + &&OPXYCB0xdc, &&OPXYCB0xdd, &&OPXYCB0xde, &&OPXYCB0xdf, + + &&OPXYCB0xe0, &&OPXYCB0xe1, &&OPXYCB0xe2, &&OPXYCB0xe3, + &&OPXYCB0xe4, &&OPXYCB0xe5, &&OPXYCB0xe6, &&OPXYCB0xe7, + &&OPXYCB0xe8, &&OPXYCB0xe9, &&OPXYCB0xea, &&OPXYCB0xeb, + &&OPXYCB0xec, &&OPXYCB0xed, &&OPXYCB0xee, &&OPXYCB0xef, + + &&OPXYCB0xf0, &&OPXYCB0xf1, &&OPXYCB0xf2, &&OPXYCB0xf3, + &&OPXYCB0xf4, &&OPXYCB0xf5, &&OPXYCB0xf6, &&OPXYCB0xf7, + &&OPXYCB0xf8, &&OPXYCB0xf9, &&OPXYCB0xfa, &&OPXYCB0xfb, + &&OPXYCB0xfc, &&OPXYCB0xfd, &&OPXYCB0xfe, &&OPXYCB0xff +}; diff --git a/waterbox/picodrive/cpu/cz80/cz80macro.h b/waterbox/picodrive/cpu/cz80/cz80macro.h new file mode 100644 index 0000000000..5adca13ae2 --- /dev/null +++ b/waterbox/picodrive/cpu/cz80/cz80macro.h @@ -0,0 +1,129 @@ +/****************************************************************************** + + cz80macro.h + + CZ80 e}N + +******************************************************************************/ + +#if CZ80_USE_JUMPTABLE +#define _SSOP(A,B) A##B +#define OP(A) _SSOP(OP,A) +#define OPCB(A) _SSOP(OPCB,A) +#define OPED(A) _SSOP(OPED,A) +#define OPXY(A) _SSOP(OPXY,A) +#define OPXYCB(A) _SSOP(OPXYCB,A) +#else +#define OP(A) case A +#define OPCB(A) case A +#define OPED(A) case A +#define OPXY(A) case A +#define OPXYCB(A) case A +#endif + +#define USE_CYCLES(A) CPU->ICount -= (A); +#define ADD_CYCLES(A) CPU->ICount += (A); + +#define RET(A) { USE_CYCLES(A) goto Cz80_Exec; } + +#if CZ80_ENCRYPTED_ROM + +#define SET_PC(A) \ + CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT]; \ + OPBase = CPU->OPFetch[(A) >> CZ80_FETCH_SFT]; \ + PC = (A) + CPU->BasePC; + +#define GET_OP() (*(UINT8 *)(OPBase + PC)) + +#else + +#define SET_PC(A) \ + CPU->BasePC = CPU->Fetch[(A) >> CZ80_FETCH_SFT]; \ + PC = (A) + CPU->BasePC; + +#define GET_OP() (*(UINT8 *)PC) + +#endif + +#define READ_OP() GET_OP(); PC++ + +#define READ_ARG() (*(UINT8 *)PC++) +#if CZ80_LITTLE_ENDIAN +#define READ_ARG16() (*(UINT8 *)PC | (*(UINT8 *)(PC + 1) << 8)); PC += 2 +#else +#define READ_ARG16() (*(UINT8 *)(PC + 1) | (*(UINT8 *)PC << 8)); PC += 2 +#endif + +//#ifndef BUILD_CPS1PSP +//#define READ_MEM8(A) memory_region_cpu2[(A)] +//#else +#if PICODRIVE_HACKS +#define READ_MEM8(A) picodrive_read(A) +#else +#define READ_MEM8(A) CPU->Read_Byte(A) +#endif +//#endif +#if CZ80_LITTLE_ENDIAN +#define READ_MEM16(A) (READ_MEM8(A) | (READ_MEM8((A) + 1) << 8)) +#else +#define READ_MEM16(A) ((READ_MEM8(A) << 8) | READ_MEM8((A) + 1)) +#endif + +#if PICODRIVE_HACKS +#define WRITE_MEM8(A, D) { \ + unsigned short a = A; \ + unsigned char d = D; \ + unsigned long v = z80_write_map[a >> Z80_MEM_SHIFT]; \ + if (map_flag_set(v)) \ + ((z80_write_f *)(v << 1))(a, d); \ + else \ + *(unsigned char *)((v << 1) + a) = d; \ +} +#else +#define WRITE_MEM8(A, D) CPU->Write_Byte(A, D); +#endif +#if CZ80_LITTLE_ENDIAN +#define WRITE_MEM16(A, D) { WRITE_MEM8(A, D); WRITE_MEM8((A) + 1, (D) >> 8); } +#else +#define WRITE_MEM16(A, D) { WRITE_MEM8((A) + 1, D); WRITE_MEM8(A, (D) >> 8); } +#endif + +#define PUSH_16(A) { UINT32 sp; zSP -= 2; sp = zSP; WRITE_MEM16(sp, A); } +#define POP_16(A) { UINT32 sp; sp = zSP; A = READ_MEM16(sp); zSP = sp + 2; } + +#define IN(A) CPU->IN_Port(A) +#define OUT(A, D) CPU->OUT_Port(A, D) + +#define CHECK_INT \ + if (zIFF1) \ + { \ + UINT32 IntVect; \ + \ + if (CPU->IRQState == HOLD_LINE) \ + CPU->IRQState = CLEAR_LINE; \ + \ + CPU->HaltState = 0; \ + zIFF1 = zIFF2 = 0; \ + IntVect = CPU->Interrupt_Callback(CPU->IRQLine); \ + \ + PUSH_16(zRealPC) \ + \ + if (zIM == 2) \ + { \ + IntVect = (IntVect & 0xff) | (zI << 8); \ + PC = READ_MEM16(IntVect); \ + CPU->ExtraCycles += 17; \ + } \ + else if (zIM == 1) \ + { \ + PC = 0x38; \ + CPU->ExtraCycles += 13; \ + } \ + else \ + { \ + PC = IntVect & 0x38; \ + CPU->ExtraCycles += 13; \ + } \ + \ + SET_PC(PC) \ + } diff --git a/waterbox/picodrive/cpu/fame/fame.h b/waterbox/picodrive/cpu/fame/fame.h new file mode 100644 index 0000000000..2f9d8508a1 --- /dev/null +++ b/waterbox/picodrive/cpu/fame/fame.h @@ -0,0 +1,165 @@ +/*****************************************************************************/ +/* FAME Fast and Accurate Motorola 68000 Emulation Core */ +/* (c) 2005 Oscar Orallo Pelaez */ +/* Version: 1.24 */ +/* Date: 08-20-2005 */ +/* See FAME.HTML for documentation and license information */ +/*****************************************************************************/ + +#ifndef __FAME_H__ +#define __FAME_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +// PicoDrive hacks +#define FAMEC_FETCHBITS 8 +#define M68K_FETCHBANK1 (1 << FAMEC_FETCHBITS) + +//#define M68K_RUNNING 0x01 +#define FM68K_HALTED 0x80 +//#define M68K_WAITING 0x04 +//#define M68K_DISABLE 0x20 +//#define M68K_FAULTED 0x40 +#define FM68K_EMULATE_GROUP_0 0x02 +#define FM68K_EMULATE_TRACE 0x08 +#define FM68K_DO_TRACE 0x10 + + +/************************************/ +/* General library defines */ +/************************************/ + +#ifndef M68K_OK + #define M68K_OK 0 +#endif +#ifndef M68K_RUNNING + #define M68K_RUNNING 1 +#endif +#ifndef M68K_NO_SUP_ADDR_SPACE + #define M68K_NO_SUP_ADDR_SPACE 2 +#endif +#ifndef M68K_DOUBLE_BUS_FAULT + #define M68K_DOUBLE_BUS_FAULT -1 +#endif +#ifndef M68K_INV_REG + #define M68K_INV_REG -1 +#endif + +/* Hardware interrupt state */ + +#ifndef M68K_IRQ_LEVEL_ERROR + #define M68K_IRQ_LEVEL_ERROR -1 +#endif +#ifndef M68K_IRQ_INV_PARAMS + #define M68K_IRQ_INV_PARAMS -2 +#endif + +/* Defines to specify hardware interrupt type */ + +#ifndef M68K_AUTOVECTORED_IRQ + #define M68K_AUTOVECTORED_IRQ -1 +#endif +#ifndef M68K_SPURIOUS_IRQ + #define M68K_SPURIOUS_IRQ -2 +#endif + +#ifndef M68K_AUTO_LOWER_IRQ + #define M68K_AUTO_LOWER_IRQ 1 +#endif +#ifndef M68K_MANUAL_LOWER_IRQ + #define M68K_MANUAL_LOWER_IRQ 0 +#endif + +/* Defines to specify address space */ + +#ifndef M68K_SUP_ADDR_SPACE + #define M68K_SUP_ADDR_SPACE 0 +#endif +#ifndef M68K_USER_ADDR_SPACE + #define M68K_USER_ADDR_SPACE 2 +#endif +#ifndef M68K_PROG_ADDR_SPACE + #define M68K_PROG_ADDR_SPACE 0 +#endif +#ifndef M68K_DATA_ADDR_SPACE + #define M68K_DATA_ADDR_SPACE 1 +#endif + + +/*******************/ +/* Data definition */ +/*******************/ + +typedef union +{ + unsigned char B; + signed char SB; + unsigned short W; + signed short SW; + unsigned int D; + signed int SD; +} famec_union32; + +/* M68K CPU CONTEXT */ +typedef struct +{ + unsigned int (*read_byte )(unsigned int a); + unsigned int (*read_word )(unsigned int a); + unsigned int (*read_long )(unsigned int a); + void (*write_byte)(unsigned int a,unsigned char d); + void (*write_word)(unsigned int a,unsigned short d); + void (*write_long)(unsigned int a,unsigned int d); + void (*reset_handler)(void); + void (*iack_handler)(unsigned level); + famec_union32 dreg[8]; + famec_union32 areg[8]; + unsigned asp; + unsigned pc; + unsigned char interrupts[8]; + unsigned short sr; + unsigned short execinfo; + // PD extension + int io_cycle_counter; // cycles left + + unsigned int Opcode; + signed int cycles_needed; + + unsigned short *PC; + unsigned long BasePC; + unsigned int flag_C; + unsigned int flag_V; + unsigned int flag_NotZ; + unsigned int flag_N; + unsigned int flag_X; + unsigned int flag_T; + unsigned int flag_S; + unsigned int flag_I; + + unsigned char not_polling; + unsigned char pad[3]; + + unsigned long Fetch[M68K_FETCHBANK1]; +} M68K_CONTEXT; + +extern M68K_CONTEXT *g_m68kcontext; + +/************************/ +/* Function definition */ +/************************/ + +/* General purpose functions */ +void fm68k_init(void); +int fm68k_reset(void); +int fm68k_emulate(int n, int idle_mode); +int fm68k_would_interrupt(void); // to be called from fm68k_emulate() + +unsigned fm68k_get_pc(M68K_CONTEXT *context); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/waterbox/picodrive/cpu/fame/famec.c b/waterbox/picodrive/cpu/fame/famec.c new file mode 100644 index 0000000000..9e9dc1535e --- /dev/null +++ b/waterbox/picodrive/cpu/fame/famec.c @@ -0,0 +1,5037 @@ +/****************************************************************************/ +/* FAME (Fast and Accurate Motorola 68000 Emulation Library) */ +/* Emulador de 68000 en C */ +/* Autor: Oscar Orallo Pelaez */ +/* Fecha de comienzo: 03-10-2006 */ +/* Ultima actualizacion: 08-10-2006 */ +/* Based on the excellent C68K emulator by Stphane Dallongueville */ +/****************************************************************************/ + +#include +#include +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#include "fame.h" + + +// Options // +#define FAMEC_ROLL_INLINE +#define FAMEC_EMULATE_TRACE +#define FAMEC_CHECK_BRANCHES +#define FAMEC_EXTRA_INLINE +// #define FAMEC_DEBUG +// #define FAMEC_NO_GOTOS +#define FAMEC_ADR_BITS 24 +// #define FAMEC_FETCHBITS 8 +#define FAMEC_DATABITS 8 +#define FAMEC_32BIT_PC + +#define USE_CYCLONE_TIMING +#define USE_CYCLONE_TIMING_DIV +#define PICODRIVE_HACK +// Options // + +#ifndef FAMEC_NO_GOTOS +// computed gotos is a GNU extension +#ifndef __GNUC__ +#define FAMEC_NO_GOTOS +#endif +// as of 3.3, clang takes over 3h to compile this in computed goto mode.. +#ifdef __clang__ +#define FAMEC_NO_GOTOS +#endif +#endif + +#undef INLINE +#ifdef _MSC_VER +#define INLINE +#else +#define INLINE __inline__ +#endif + +#ifndef FAMEC_EXTRA_INLINE +#define FAMEC_EXTRA_INLINE +#else +#undef FAMEC_EXTRA_INLINE +#define FAMEC_EXTRA_INLINE INLINE +#endif + +#ifdef u8 +#undef u8 +#endif + +#ifdef s8 +#undef s8 +#endif + +#ifdef u16 +#undef u16 +#endif + +#ifdef s16 +#undef s16 +#endif + +#ifdef u32 +#undef u32 +#endif + +#ifdef s32 +#undef s32 +#endif + +#ifdef uptr +#undef uptr +#endif + +#define u8 unsigned char +#define s8 signed char +#define u16 unsigned short +#define s16 signed short +#define u32 unsigned int +#define s32 signed int +#define uptr unsigned long + +/* +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned int u32; +typedef signed int s32; +*/ + +#ifndef M68K_OK + #define M68K_OK 0 +#endif + +#ifndef M68K_RUNNING + #define M68K_RUNNING 1 +#endif + +#ifndef M68K_NO_SUP_ADDR_SPACE + #define M68K_NO_SUP_ADDR_SPACE 2 +#endif + +#ifndef M68K_INV_REG + #define M68K_INV_REG -1 +#endif + +/* Hardware interrupt state */ + +#ifndef M68K_IRQ_LEVEL_ERROR + #define M68K_IRQ_LEVEL_ERROR -1 +#endif + +#ifndef M68K_IRQ_INV_PARAMS + #define M68K_IRQ_INV_PARAMS -2 +#endif + +/* Defines to specify hardware interrupt type */ + +#ifndef M68K_AUTOVECTORED_IRQ + #define M68K_AUTOVECTORED_IRQ -1 +#endif + +#ifndef M68K_SPURIOUS_IRQ + #define M68K_SPURIOUS_IRQ -2 +#endif + +/* Defines to specify address space */ + +#ifndef M68K_SUP_ADDR_SPACE + #define M68K_SUP_ADDR_SPACE 0 +#endif + +#ifndef M68K_USER_ADDR_SPACE + #define M68K_USER_ADDR_SPACE 2 +#endif + +#ifndef M68K_PROG_ADDR_SPACE + #define M68K_PROG_ADDR_SPACE 0 +#endif + +#ifndef M68K_DATA_ADDR_SPACE + #define M68K_DATA_ADDR_SPACE 1 +#endif + + + +/******************************/ +/* 68K core types definitions */ +/******************************/ + +#if FAMEC_ADR_BITS < 32 +#define M68K_ADR_MASK ((1 << FAMEC_ADR_BITS)-1) +#else +#define M68K_ADR_MASK 0xFFFFFFFF +#endif +#define M68K_FETCHSFT (FAMEC_ADR_BITS - FAMEC_FETCHBITS) +#define M68K_FETCHBANK (1 << FAMEC_FETCHBITS) +#define M68K_FETCHMASK (M68K_FETCHBANK - 1) + +#define M68K_DATASFT (FAMEC_ADR_BITS - FAMEC_DATABITS) +#define M68K_DATABANK (1 << FAMEC_DATABITS) +#define M68K_DATAMASK (M68K_DATABANK - 1) + +#define M68K_SR_C_SFT 8 +#define M68K_SR_V_SFT 7 +#define M68K_SR_Z_SFT 0 +#define M68K_SR_N_SFT 7 +#define M68K_SR_X_SFT 8 + +#define M68K_SR_S_SFT 13 +#define M68K_SR_T_SFT 15 + +#define M68K_SR_C (1 << M68K_SR_C_SFT) +#define M68K_SR_V (1 << M68K_SR_V_SFT) +#define M68K_SR_Z 0 +#define M68K_SR_N (1 << M68K_SR_N_SFT) +#define M68K_SR_X (1 << M68K_SR_X_SFT) + +#define M68K_SR_S (1 << M68K_SR_S_SFT) +#define M68K_SR_T (1 << M68K_SR_T_SFT) + +#define M68K_CCR_MASK 0x1F + +#ifdef FAMEC_EMULATE_TRACE +#define M68K_SR_MASK (M68K_SR_T | M68K_SR_S | 0x0700 | M68K_CCR_MASK) +#else +#define M68K_SR_MASK (M68K_SR_S | 0x0700 | M68K_CCR_MASK) +#endif + +// exception defines taken from musashi core +#define M68K_RESET_EX 1 +#define M68K_BUS_ERROR_EX 2 +#define M68K_ADDRESS_ERROR_EX 3 +#define M68K_ILLEGAL_INSTRUCTION_EX 4 +#define M68K_ZERO_DIVIDE_EX 5 +#define M68K_CHK_EX 6 +#define M68K_TRAPV_EX 7 +#define M68K_PRIVILEGE_VIOLATION_EX 8 +#define M68K_TRACE_EX 9 +#define M68K_1010_EX 10 +#define M68K_1111_EX 11 +#define M68K_FORMAT_ERROR_EX 14 +#define M68K_UNINITIALIZED_INTERRUPT_EX 15 +#define M68K_SPURIOUS_INTERRUPT_EX 24 +#define M68K_INTERRUPT_AUTOVECTOR_EX 24 +#define M68K_TRAP_BASE_EX 32 + +#define M68K_INT_ACK_AUTOVECTOR -1 + + +// internals core macros +///////////////////////// + +#define DREG(X) (m68kcontext.dreg[(X)].D) +#define DREGu32(X) (m68kcontext.dreg[(X)].D) +#define DREGs32(X) (m68kcontext.dreg[(X)].SD) +#define DREGu16(X) (m68kcontext.dreg[(X)].W) +#define DREGs16(X) (m68kcontext.dreg[(X)].SW) +#define DREGu8(X) (m68kcontext.dreg[(X)].B) +#define DREGs8(X) (m68kcontext.dreg[(X)].SB) + +#define AREG(X) (m68kcontext.areg[(X)].D) +#define AREGu32(X) (m68kcontext.areg[(X)].D) +#define AREGs32(X) (m68kcontext.areg[(X)].SD) +#define AREGu16(X) (m68kcontext.areg[(X)].W) +#define AREGs16(X) (m68kcontext.areg[(X)].SW) + +#define ASP (m68kcontext.asp) + +#define LSL(A, C) ((A) << (C)) +#define LSR(A, C) ((A) >> (C)) + +#define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) +#define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) + +#define ROL_8(A, C) (LSL(A, C) | LSR(A, 8-(C))) +#define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C))) +#define ROL_16(A, C) (LSL(A, C) | LSR(A, 16-(C))) +#define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C))) +#define ROL_32(A, C) (LSL_32(A, C) | LSR_32(A, 32-(C))) +#define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C))) + +#define ROR_8(A, C) (LSR(A, C) | LSL(A, 8-(C))) +#define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C))) +#define ROR_16(A, C) (LSR(A, C) | LSL(A, 16-(C))) +#define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C))) +#define ROR_32(A, C) (LSR_32(A, C) | LSL_32(A, 32-(C))) +#define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C))) + +#ifndef FAMEC_NO_GOTOS +#define NEXT \ + FETCH_WORD(Opcode); \ + goto *JumpTable[Opcode]; + +#ifdef FAMEC_ROLL_INLINE +#define RET(A) \ + m68kcontext.io_cycle_counter -= (A); \ + if (m68kcontext.io_cycle_counter <= 0) goto famec_Exec_End; \ + NEXT +#else +#define RET(A) \ + m68kcontext.io_cycle_counter -= (A); \ + if (m68kcontext.io_cycle_counter <= 0) goto famec_Exec_End; \ + goto famec_Exec; +#endif + +#define RET0() \ + m68kcontext.io_cycle_counter = -6; \ + goto famec_End; + +#else + +#define NEXT \ + do{ \ + FETCH_WORD(Opcode); \ + JumpTable[Opcode](); \ + }while(m68kcontext.io_cycle_counter>0); + +#define RET(A) \ + m68kcontext.io_cycle_counter -= (A); \ + return; + +#define RET0() \ + m68kcontext.io_cycle_counter = -6; \ + return; + +#endif + +#define M68K_PPL (m68kcontext.sr >> 8) & 7 + +#define GET_PC \ + (u32)((uptr)PC - BasePC) + + +#ifdef FAMEC_CHECK_BRANCHES +#define FORCE_ALIGNMENT(pc) +#else +#define FORCE_ALIGNMENT(pc) pc&=~1; +#endif + +#ifndef FAMEC_32BIT_PC + +#define SET_PC(A) \ +{ \ + u32 pc = A; \ + FORCE_ALIGNMENT(pc); \ + BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \ + PC = (u16*)((pc & M68K_ADR_MASK) + BasePC); \ +} + +#else + +#define SET_PC(A) \ +{ \ + u32 pc = A; \ + FORCE_ALIGNMENT(pc); \ + BasePC = m68kcontext.Fetch[(pc >> M68K_FETCHSFT) & M68K_FETCHMASK]; \ + BasePC -= pc & 0xFF000000; \ + PC = (u16*)(pc + BasePC); \ +} + +#endif + + +#define PRE_IO \ +// io_cycle_counter = CCnt; + +#define POST_IO \ +// CCnt = io_cycle_counter; + +#define READ_BYTE_F(A, D) \ + D = m68kcontext.read_byte(A) & 0xFF; + +#define READ_WORD_F(A, D) \ + D = m68kcontext.read_word(A) & 0xFFFF; + +#define READ_LONG_F(A, D) \ + D = m68kcontext.read_long(A); + +#define READSX_LONG_F READ_LONG_F + +#define WRITE_LONG_F(A, D) \ + m68kcontext.write_long(A, D); + +#define WRITE_LONG_DEC_F(A, D) \ + m68kcontext.write_word((A) + 2, (D) & 0xFFFF); \ + m68kcontext.write_word((A), (D) >> 16); + +#define PUSH_32_F(D) \ + AREG(7) -= 4; \ + m68kcontext.write_long(AREG(7), D); + +#define POP_32_F(D) \ + D = m68kcontext.read_long(AREG(7)); \ + AREG(7) += 4; + +#ifndef FAME_BIG_ENDIAN + + #define FETCH_LONG(A) \ + (A) = PC[1] | (PC[0] << 16); \ + PC += 2; + + #define GET_SWORD \ + (s16)(*PC) + + #define FETCH_BYTE(A) \ + (A) = (*PC++) & 0xFF; + + #define FETCH_SBYTE(A) \ + (A) = (s8)((*PC++) & 0xFF); + + #define FETCH_WORD(A) \ + (A) = *PC++; + + #define FETCH_SWORD(A) \ + (A) = (s16)(*PC++); + + #define DECODE_EXT_WORD \ + { \ + u32 ext; \ + \ + ext = *PC++; \ + \ + adr += (s8)(ext); \ + if (ext & 0x0800) adr += DREGs32(ext >> 12); \ + else adr += DREGs16(ext >> 12); \ + } + +#else + + #define FETCH_LONG(A) \ + (A) = PC[0] | (PC[1] << 16); \ + PC += 2; + + #define GET_SWORD \ + ((s16)(((*PC & 0xFF) << 8) | (*PC >> 8))) + + #define FETCH_BYTE(A) \ + (A) = (*PC++) >> 8; + + #define FETCH_SBYTE(A) \ + (A) = (s8)((*PC++) >> 8); + + #define FETCH_WORD(A) \ + (A) = ((*PC & 0xFF) << 8) | (*PC >> 8); \ + PC++; + + #define FETCH_SWORD(A) \ + (A) = (s16)(((*PC & 0xFF) << 8) | (*PC >> 8)); \ + PC++; + + #define DECODE_EXT_WORD \ + { \ + u32 ext; \ + \ + ext = *PC++; \ + \ + adr += (s8)(ext >> 8); \ + if (ext & 0x0008) adr += DREGs32((ext >> 4) & 0x000F); \ + else adr += DREGs16((ext >> 4) & 0x000F); \ + } + +#endif + +#define READSX_BYTE_F(A, D) \ + D = (s8)m68kcontext.read_byte(A); + +#define READSX_WORD_F(A, D) \ + D = (s16)m68kcontext.read_word(A); + + +#define WRITE_BYTE_F(A, D) \ + m68kcontext.write_byte(A, D); + +#define WRITE_WORD_F(A, D) \ + m68kcontext.write_word(A, D); + +#define PUSH_16_F(D) \ + m68kcontext.write_word(AREG(7) -= 2, D); \ + +#define POP_16_F(D) \ + D = (u16)m68kcontext.read_word(AREG(7)); \ + AREG(7) += 2; + +#define GET_CCR \ + (((flag_C >> (M68K_SR_C_SFT - 0)) & 1) | \ + ((flag_V >> (M68K_SR_V_SFT - 1)) & 2) | \ + (((!flag_NotZ) & 1) << 2) | \ + ((flag_N >> (M68K_SR_N_SFT - 3)) & 8) | \ + ((flag_X >> (M68K_SR_X_SFT - 4)) & 0x10)) + +#ifdef FAMEC_EMULATE_TRACE +#define GET_SR \ + ((flag_S << 0) | \ + (flag_I << 8) | \ + (flag_T ) | \ + GET_CCR) +#else +#define GET_SR \ + ((flag_S << 0) | \ + (flag_I << 8) | \ + GET_CCR) +#endif + +#define SET_CCR(A) \ + flag_C = (A) << (M68K_SR_C_SFT - 0); \ + flag_V = (A) << (M68K_SR_V_SFT - 1); \ + flag_NotZ = ~(A) & 4; \ + flag_N = (A) << (M68K_SR_N_SFT - 3); \ + flag_X = (A) << (M68K_SR_X_SFT - 4); + + +#ifdef FAMEC_EMULATE_TRACE +#define SET_SR(A) \ + SET_CCR(A) \ + flag_T = (A) & M68K_SR_T; \ + flag_S = (A) & M68K_SR_S; \ + flag_I = ((A) >> 8) & 7; +#else +#define SET_SR(A) \ + SET_CCR(A) \ + flag_S = (A) & M68K_SR_S; \ + flag_I = ((A) >> 8) & 7; +#endif + +#define CHECK_INT_TO_JUMP(CLK) \ + if (interrupt_chk__()) \ + { \ + cycles_needed=m68kcontext.io_cycle_counter-(CLK); \ + m68kcontext.io_cycle_counter=(CLK); \ + } + + +#ifdef FAMEC_CHECK_BRANCHES + +#ifdef FAMEC_NO_GOTOS +#define CHECK_BRANCH_EXCEPTION_GOTO_END m68kcontext.io_cycle_counter=0; return; +#else +#define CHECK_BRANCH_EXCEPTION_GOTO_END goto famec_Exec_End; +#endif + +#define CHECK_BRANCH_EXCEPTION(_PC_) \ + if ((_PC_)&1) \ + { \ + u32 new_PC, pr_PC=GET_PC; \ + m68kcontext.execinfo |= FM68K_EMULATE_GROUP_0; \ + new_PC = execute_exception_group_0(M68K_ADDRESS_ERROR_EX, 0, pr_PC, 0x12 ); \ + SET_PC(new_PC); \ + CHECK_BRANCH_EXCEPTION_GOTO_END \ + } +#else +#define CHECK_BRANCH_EXCEPTION(_PC_) +#endif + + +// global variable +/////////////////// + +/* Current CPU context */ +M68K_CONTEXT *g_m68kcontext; +#define m68kcontext (*g_m68kcontext) + +#ifdef FAMEC_NO_GOTOS +#define Opcode m68kcontext.Opcode +#define cycles_needed m68kcontext.cycles_needed +#define PC m68kcontext.PC +#define BasePC m68kcontext.BasePC +#define flag_C m68kcontext.flag_C +#define flag_V m68kcontext.flag_V +#define flag_NotZ m68kcontext.flag_NotZ +#define flag_N m68kcontext.flag_N +#define flag_X m68kcontext.flag_X +#endif + +#define flag_T m68kcontext.flag_T +#define flag_S m68kcontext.flag_S +#define flag_I m68kcontext.flag_I + +static u32 initialised = 0; + +#ifdef PICODRIVE_HACK +extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; +#endif + +/* Custom function handler */ +typedef void (*opcode_func)(void); + +static opcode_func JumpTable[0x10000]; + +// exception cycle table (taken from musashi core) +static const s32 exception_cycle_table[256] = +{ + 4, // 0: Reset - Initial Stack Pointer + 4, // 1: Reset - Initial Program Counter + 50, // 2: Bus Error + 50, // 3: Address Error + 34, // 4: Illegal Instruction + 38, // 5: Divide by Zero + 40, // 6: CHK + 34, // 7: TRAPV + 34, // 8: Privilege Violation + 34, // 9: Trace + 4, // 10: + 4, // 11: + 4, // 12: RESERVED + 4, // 13: Coprocessor Protocol Violation + 4, // 14: Format Error + 44, // 15: Uninitialized Interrupt + 4, // 16: RESERVED + 4, // 17: RESERVED + 4, // 18: RESERVED + 4, // 19: RESERVED + 4, // 20: RESERVED + 4, // 21: RESERVED + 4, // 22: RESERVED + 4, // 23: RESERVED + 44, // 24: Spurious Interrupt + 44, // 25: Level 1 Interrupt Autovector + 44, // 26: Level 2 Interrupt Autovector + 44, // 27: Level 3 Interrupt Autovector + 44, // 28: Level 4 Interrupt Autovector + 44, // 29: Level 5 Interrupt Autovector + 44, // 30: Level 6 Interrupt Autovector + 44, // 31: Level 7 Interrupt Autovector + 34, // 32: TRAP #0 + 34, // 33: TRAP #1 + 34, // 34: TRAP #2 + 34, // 35: TRAP #3 + 34, // 36: TRAP #4 + 34, // 37: TRAP #5 + 34, // 38: TRAP #6 + 34, // 39: TRAP #7 + 34, // 40: TRAP #8 + 34, // 41: TRAP #9 + 34, // 42: TRAP #10 + 34, // 43: TRAP #11 + 34, // 44: TRAP #12 + 34, // 45: TRAP #13 + 34, // 46: TRAP #14 + 34, // 47: TRAP #15 + 4, // 48: FP Branch or Set on Unknown Condition + 4, // 49: FP Inexact Result + 4, // 50: FP Divide by Zero + 4, // 51: FP Underflow + 4, // 52: FP Operand Error + 4, // 53: FP Overflow + 4, // 54: FP Signaling NAN + 4, // 55: FP Unimplemented Data Type + 4, // 56: MMU Configuration Error + 4, // 57: MMU Illegal Operation Error + 4, // 58: MMU Access Level Violation Error + 4, // 59: RESERVED + 4, // 60: RESERVED + 4, // 61: RESERVED + 4, // 62: RESERVED + 4, // 63: RESERVED + // 64-255: User Defined + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 +}; + + +/***********************/ +/* core main functions */ +/***********************/ + +/***************************************************************************/ +/* m68k_init() */ +/* Debe ser llamado para inicializar la tabla de saltos de instruccion */ +/* No recibe parametros y no devuelve nada */ +/***************************************************************************/ +void fm68k_init(void) +{ +#ifdef FAMEC_DEBUG + puts("Initializing FAME..."); +#endif + + if (!initialised) + fm68k_emulate(0, 0); + +#ifdef FAMEC_DEBUG + puts("FAME initialized."); +#endif +} + +/******************************************************************************/ +/* m68k_reset() */ +/* Parametros: Ninguno */ +/* Retorno: Exito de la operacion */ +/* M68K_OK (0): La funcion se ha ejecutado satisfactoriamente */ +/* M68K_RUNNING (1): No se puede resetear porque la CPU esta en ejecucion */ +/* M68K_NO_SUP_ADDR_SPACE (2): No se puede resetear porque no hay mapa */ +/* de memoria supervisor de extraccion de opcodes */ +/******************************************************************************/ +int fm68k_reset(void) +{ + if (!initialised) + fm68k_emulate(0, 0); + + // Si la CPU esta en ejecucion, salir con M68K_RUNNING + if (m68kcontext.execinfo & M68K_RUNNING) + return M68K_RUNNING; + + // Resetear registros + //memset(&m68kcontext.dreg[0], 0, 16*4); + + // Resetear interrupts, execinfo y ASP + m68kcontext.interrupts[0] = 0; + m68kcontext.execinfo = 0; + ASP = 0; + + // Fijar registro de estado + m68kcontext.sr = (m68kcontext.sr & 0xff) | 0x2700; + + // Obtener puntero de pila inicial y PC + AREG(7) = m68kcontext.read_long(0); + m68kcontext.pc = m68kcontext.read_long(4); + +#ifdef FAMEC_DEBUG + puts("Reset 68k done!\n"); + printf("PC = 0x%08X\n",m68kcontext.pc); +#endif + + return M68K_OK; +} + + +/****************************************************************************/ +/* m68k_get_pc() */ +/* No recibe parametros */ +/* Retorna 68k PC */ +/****************************************************************************/ +u32 fm68k_get_pc(M68K_CONTEXT *context) +{ +#ifdef FAMEC_NO_GOTOS + return (context->execinfo & M68K_RUNNING)?(uptr)PC-BasePC:context->pc; +#else + return context->pc; // approximate PC in this mode +#endif +} + + +////////////////////////// +// Chequea las interrupciones y las inicia +static FAMEC_EXTRA_INLINE s32 interrupt_chk__(void) +{ + if (m68kcontext.interrupts[0] > flag_I) + return m68kcontext.interrupts[0]; + + return 0; +} + +int fm68k_would_interrupt(void) +{ + return interrupt_chk__(); +} + +static FAMEC_EXTRA_INLINE u32 execute_exception(s32 vect, u32 oldPC, u32 oldSR) +{ + u32 newPC; + //u32 oldSR = GET_SR; + + m68kcontext.io_cycle_counter -= exception_cycle_table[vect]; + + PRE_IO + + READ_LONG_F(vect * 4, newPC) + + /* swap A7 and USP */ + if (!flag_S) + { + u32 tmpSP; + + tmpSP = ASP; + ASP = AREG(7); + AREG(7) = tmpSP; + } + + //oldPC = GET_PC; + PUSH_32_F(oldPC) + PUSH_16_F(oldSR) + + /* adjust SR */ + flag_S = M68K_SR_S; + +#ifndef FAMEC_32BIT_PC + newPC&=M68K_ADR_MASK +#endif +#ifdef FAMEC_CHECK_BRANCHES + newPC&=~1; // don't crash on games with bad vector tables +#endif + + // SET_PC(newPC) + + POST_IO + + return newPC; +} + +static FAMEC_EXTRA_INLINE u32 execute_exception_group_0(s32 vect, s32 addr, u16 spec_info, u32 oldSR) +{ + u32 newPC; + u16 inst_reg = 0; + newPC = execute_exception(vect, addr, oldSR); + //if (!(m68kcontext.icust_handler && m68kcontext.icust_handler[vect])) + { + PUSH_16_F(inst_reg); + PUSH_32_F(addr); + PUSH_16_F(spec_info); + } + return newPC; +} + + +#ifdef FAMEC_NO_GOTOS + +#define OPCODE(N_OP) static void OP_##N_OP(void) +#define CAST_OP(N_OP) (opcode_func)&OP_##N_OP +#include "famec_opcodes.h" +#endif + + +// main exec function +////////////////////// + +int fm68k_emulate(s32 cycles, int idle_mode) +{ +#ifndef FAMEC_NO_GOTOS + u32 Opcode; + s32 cycles_needed; + u16 *PC; + uptr BasePC; + u32 flag_C; + u32 flag_V; + u32 flag_NotZ; + u32 flag_N; + u32 flag_X; +#endif + + if (!initialised) + { + goto init_jump_table; + } + +#ifdef PICODRIVE_HACK + if (idle_mode == 1) goto idle_install; + else if (idle_mode == 2) goto idle_remove; +#endif + + // won't emulate double fault + // if (m68kcontext.execinfo & M68K_FAULTED) return -1; + + // Cache PPL + flag_I = M68K_PPL; + + if (m68kcontext.execinfo & FM68K_HALTED) + { + if (interrupt_chk__() <= 0) + { + return cycles; + } + m68kcontext.execinfo &= ~FM68K_HALTED; + } + +#ifdef FAMEC_DEBUG + printf("Ciclos a ejecutar: %d\n",cycles); +#endif + + /* Poner la CPU en estado de ejecucion */ + m68kcontext.execinfo |= M68K_RUNNING; + + // Cache SR + SET_SR(m68kcontext.sr) + + // Fijar PC + SET_PC(m68kcontext.pc) + +#ifdef FAMEC_DEBUG + printf("PC: %p\n",PC); + printf("BasePC: 0x%08x\n",BasePC); +#endif + + /* guardar ciclos de ejecucion solicitados */ + m68kcontext.io_cycle_counter = cycles; + cycles_needed = 0; + +#ifdef FAMEC_EMULATE_TRACE + if (!(m68kcontext.execinfo & FM68K_EMULATE_TRACE)) +#endif + { + s32 line=interrupt_chk__(); + if (line>0) + { + /* comprobar si hay rutina de acknowledge */ + if (m68kcontext.iack_handler != NULL) + m68kcontext.iack_handler(line); + else + m68kcontext.interrupts[0] = 0; + + SET_PC(execute_exception(line + 0x18, GET_PC, GET_SR)); + flag_I = (u32)line; + if (m68kcontext.io_cycle_counter <= 0) goto famec_End; + } +#ifdef FAMEC_EMULATE_TRACE + else + if (flag_T) + { + m68kcontext.execinfo |= FM68K_EMULATE_TRACE; + cycles_needed = m68kcontext.io_cycle_counter; + m68kcontext.io_cycle_counter=0; + } +#endif + } + + +//#ifndef FAMEC_NO_GOTOS +famec_Exec: +//#endif + +#ifdef FAMEC_DEBUG + printf("Antes de NEXT... PC = %p\n", PC); +#endif + + NEXT + +#ifndef FAMEC_NO_GOTOS + +#define OPCODE(N_OP) OP_##N_OP: +#define CAST_OP(N_OP) (opcode_func)&&OP_##N_OP +#include "famec_opcodes.h" + + famec_Exec_End: +#endif + +#ifdef FAMEC_EMULATE_TRACE + if (m68kcontext.execinfo & FM68K_EMULATE_TRACE) + { + m68kcontext.io_cycle_counter = cycles_needed; + cycles_needed = 0; + m68kcontext.execinfo &= ~FM68K_EMULATE_TRACE; + m68kcontext.execinfo |= FM68K_DO_TRACE; + SET_PC(execute_exception(M68K_TRACE_EX, GET_PC, GET_SR)); + flag_T=0; + if (m68kcontext.io_cycle_counter > 0) + { + //NEXT + goto famec_Exec; + } + } + else +#endif + if (cycles_needed != 0) + { + u32 line; + m68kcontext.io_cycle_counter = cycles_needed; + cycles_needed = 0; + if (m68kcontext.io_cycle_counter <= 0) goto famec_End; + line=interrupt_chk__(); + if (line>0) + { + if (m68kcontext.iack_handler != NULL) + m68kcontext.iack_handler(line); + else + m68kcontext.interrupts[0] = 0; + + SET_PC(execute_exception(line + 0x18, GET_PC, GET_SR)); + flag_I = (u32)line; + } +#ifdef FAMEC_EMULATE_TRACE + if (!(flag_T)) +#endif + if (m68kcontext.io_cycle_counter > 0) + { + //NEXT + goto famec_Exec; + } + } + +famec_End: + m68kcontext.sr = GET_SR; + m68kcontext.pc = GET_PC; + + m68kcontext.execinfo &= ~M68K_RUNNING; + +#ifdef FAMEC_DEBUG + printf("En really end...\n"); + printf("PC: %p\n",PC); + printf("BasePC: 0x%08x\n",BasePC); + printf("pc: 0x%08x\n",m68kcontext.pc); +#endif + + return cycles - m68kcontext.io_cycle_counter; + +init_jump_table: +{ + u32 i, j; + + for(i = 0x0000; i <= 0xFFFF; i += 0x0001) + JumpTable[0x0000 + i] = CAST_OP(0x4AFC); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0000 + i] = CAST_OP(0x0000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0010 + i] = CAST_OP(0x0010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0018 + i] = CAST_OP(0x0018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0020 + i] = CAST_OP(0x0020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0028 + i] = CAST_OP(0x0028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0030 + i] = CAST_OP(0x0030); + JumpTable[0x0038] = CAST_OP(0x0038); + JumpTable[0x0039] = CAST_OP(0x0039); + JumpTable[0x001F] = CAST_OP(0x001F); + JumpTable[0x0027] = CAST_OP(0x0027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0040 + i] = CAST_OP(0x0040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0050 + i] = CAST_OP(0x0050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0058 + i] = CAST_OP(0x0058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0060 + i] = CAST_OP(0x0060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0068 + i] = CAST_OP(0x0068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0070 + i] = CAST_OP(0x0070); + JumpTable[0x0078] = CAST_OP(0x0078); + JumpTable[0x0079] = CAST_OP(0x0079); + JumpTable[0x005F] = CAST_OP(0x005F); + JumpTable[0x0067] = CAST_OP(0x0067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0080 + i] = CAST_OP(0x0080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0090 + i] = CAST_OP(0x0090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0098 + i] = CAST_OP(0x0098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x00A0 + i] = CAST_OP(0x00A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x00A8 + i] = CAST_OP(0x00A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x00B0 + i] = CAST_OP(0x00B0); + JumpTable[0x00B8] = CAST_OP(0x00B8); + JumpTable[0x00B9] = CAST_OP(0x00B9); + JumpTable[0x009F] = CAST_OP(0x009F); + JumpTable[0x00A7] = CAST_OP(0x00A7); + JumpTable[0x003C] = CAST_OP(0x003C); + JumpTable[0x007C] = CAST_OP(0x007C); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0200 + i] = CAST_OP(0x0200); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0210 + i] = CAST_OP(0x0210); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0218 + i] = CAST_OP(0x0218); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0220 + i] = CAST_OP(0x0220); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0228 + i] = CAST_OP(0x0228); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0230 + i] = CAST_OP(0x0230); + JumpTable[0x0238] = CAST_OP(0x0238); + JumpTable[0x0239] = CAST_OP(0x0239); + JumpTable[0x021F] = CAST_OP(0x021F); + JumpTable[0x0227] = CAST_OP(0x0227); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0240 + i] = CAST_OP(0x0240); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0250 + i] = CAST_OP(0x0250); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0258 + i] = CAST_OP(0x0258); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0260 + i] = CAST_OP(0x0260); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0268 + i] = CAST_OP(0x0268); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0270 + i] = CAST_OP(0x0270); + JumpTable[0x0278] = CAST_OP(0x0278); + JumpTable[0x0279] = CAST_OP(0x0279); + JumpTable[0x025F] = CAST_OP(0x025F); + JumpTable[0x0267] = CAST_OP(0x0267); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0280 + i] = CAST_OP(0x0280); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0290 + i] = CAST_OP(0x0290); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0298 + i] = CAST_OP(0x0298); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x02A0 + i] = CAST_OP(0x02A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x02A8 + i] = CAST_OP(0x02A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x02B0 + i] = CAST_OP(0x02B0); + JumpTable[0x02B8] = CAST_OP(0x02B8); + JumpTable[0x02B9] = CAST_OP(0x02B9); + JumpTable[0x029F] = CAST_OP(0x029F); + JumpTable[0x02A7] = CAST_OP(0x02A7); + JumpTable[0x023C] = CAST_OP(0x023C); + JumpTable[0x027C] = CAST_OP(0x027C); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A00 + i] = CAST_OP(0x0A00); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A10 + i] = CAST_OP(0x0A10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0A18 + i] = CAST_OP(0x0A18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0A20 + i] = CAST_OP(0x0A20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A28 + i] = CAST_OP(0x0A28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A30 + i] = CAST_OP(0x0A30); + JumpTable[0x0A38] = CAST_OP(0x0A38); + JumpTable[0x0A39] = CAST_OP(0x0A39); + JumpTable[0x0A1F] = CAST_OP(0x0A1F); + JumpTable[0x0A27] = CAST_OP(0x0A27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A40 + i] = CAST_OP(0x0A40); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A50 + i] = CAST_OP(0x0A50); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0A58 + i] = CAST_OP(0x0A58); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0A60 + i] = CAST_OP(0x0A60); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A68 + i] = CAST_OP(0x0A68); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A70 + i] = CAST_OP(0x0A70); + JumpTable[0x0A78] = CAST_OP(0x0A78); + JumpTable[0x0A79] = CAST_OP(0x0A79); + JumpTable[0x0A5F] = CAST_OP(0x0A5F); + JumpTable[0x0A67] = CAST_OP(0x0A67); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A80 + i] = CAST_OP(0x0A80); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0A90 + i] = CAST_OP(0x0A90); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0A98 + i] = CAST_OP(0x0A98); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0AA0 + i] = CAST_OP(0x0AA0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0AA8 + i] = CAST_OP(0x0AA8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0AB0 + i] = CAST_OP(0x0AB0); + JumpTable[0x0AB8] = CAST_OP(0x0AB8); + JumpTable[0x0AB9] = CAST_OP(0x0AB9); + JumpTable[0x0A9F] = CAST_OP(0x0A9F); + JumpTable[0x0AA7] = CAST_OP(0x0AA7); + JumpTable[0x0A3C] = CAST_OP(0x0A3C); + JumpTable[0x0A7C] = CAST_OP(0x0A7C); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0400 + i] = CAST_OP(0x0400); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0410 + i] = CAST_OP(0x0410); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0418 + i] = CAST_OP(0x0418); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0420 + i] = CAST_OP(0x0420); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0428 + i] = CAST_OP(0x0428); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0430 + i] = CAST_OP(0x0430); + JumpTable[0x0438] = CAST_OP(0x0438); + JumpTable[0x0439] = CAST_OP(0x0439); + JumpTable[0x041F] = CAST_OP(0x041F); + JumpTable[0x0427] = CAST_OP(0x0427); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0440 + i] = CAST_OP(0x0440); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0450 + i] = CAST_OP(0x0450); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0458 + i] = CAST_OP(0x0458); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0460 + i] = CAST_OP(0x0460); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0468 + i] = CAST_OP(0x0468); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0470 + i] = CAST_OP(0x0470); + JumpTable[0x0478] = CAST_OP(0x0478); + JumpTable[0x0479] = CAST_OP(0x0479); + JumpTable[0x045F] = CAST_OP(0x045F); + JumpTable[0x0467] = CAST_OP(0x0467); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0480 + i] = CAST_OP(0x0480); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0490 + i] = CAST_OP(0x0490); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0498 + i] = CAST_OP(0x0498); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x04A0 + i] = CAST_OP(0x04A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x04A8 + i] = CAST_OP(0x04A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x04B0 + i] = CAST_OP(0x04B0); + JumpTable[0x04B8] = CAST_OP(0x04B8); + JumpTable[0x04B9] = CAST_OP(0x04B9); + JumpTable[0x049F] = CAST_OP(0x049F); + JumpTable[0x04A7] = CAST_OP(0x04A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0600 + i] = CAST_OP(0x0600); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0610 + i] = CAST_OP(0x0610); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0618 + i] = CAST_OP(0x0618); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0620 + i] = CAST_OP(0x0620); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0628 + i] = CAST_OP(0x0628); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0630 + i] = CAST_OP(0x0630); + JumpTable[0x0638] = CAST_OP(0x0638); + JumpTable[0x0639] = CAST_OP(0x0639); + JumpTable[0x061F] = CAST_OP(0x061F); + JumpTable[0x0627] = CAST_OP(0x0627); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0640 + i] = CAST_OP(0x0640); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0650 + i] = CAST_OP(0x0650); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0658 + i] = CAST_OP(0x0658); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0660 + i] = CAST_OP(0x0660); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0668 + i] = CAST_OP(0x0668); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0670 + i] = CAST_OP(0x0670); + JumpTable[0x0678] = CAST_OP(0x0678); + JumpTable[0x0679] = CAST_OP(0x0679); + JumpTable[0x065F] = CAST_OP(0x065F); + JumpTable[0x0667] = CAST_OP(0x0667); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0680 + i] = CAST_OP(0x0680); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0690 + i] = CAST_OP(0x0690); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0698 + i] = CAST_OP(0x0698); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x06A0 + i] = CAST_OP(0x06A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x06A8 + i] = CAST_OP(0x06A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x06B0 + i] = CAST_OP(0x06B0); + JumpTable[0x06B8] = CAST_OP(0x06B8); + JumpTable[0x06B9] = CAST_OP(0x06B9); + JumpTable[0x069F] = CAST_OP(0x069F); + JumpTable[0x06A7] = CAST_OP(0x06A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C00 + i] = CAST_OP(0x0C00); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C10 + i] = CAST_OP(0x0C10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0C18 + i] = CAST_OP(0x0C18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0C20 + i] = CAST_OP(0x0C20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C28 + i] = CAST_OP(0x0C28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C30 + i] = CAST_OP(0x0C30); + JumpTable[0x0C38] = CAST_OP(0x0C38); + JumpTable[0x0C39] = CAST_OP(0x0C39); + JumpTable[0x0C1F] = CAST_OP(0x0C1F); + JumpTable[0x0C27] = CAST_OP(0x0C27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C40 + i] = CAST_OP(0x0C40); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C50 + i] = CAST_OP(0x0C50); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0C58 + i] = CAST_OP(0x0C58); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0C60 + i] = CAST_OP(0x0C60); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C68 + i] = CAST_OP(0x0C68); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C70 + i] = CAST_OP(0x0C70); + JumpTable[0x0C78] = CAST_OP(0x0C78); + JumpTable[0x0C79] = CAST_OP(0x0C79); + JumpTable[0x0C5F] = CAST_OP(0x0C5F); + JumpTable[0x0C67] = CAST_OP(0x0C67); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C80 + i] = CAST_OP(0x0C80); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0C90 + i] = CAST_OP(0x0C90); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0C98 + i] = CAST_OP(0x0C98); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0CA0 + i] = CAST_OP(0x0CA0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0CA8 + i] = CAST_OP(0x0CA8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0CB0 + i] = CAST_OP(0x0CB0); + JumpTable[0x0CB8] = CAST_OP(0x0CB8); + JumpTable[0x0CB9] = CAST_OP(0x0CB9); + JumpTable[0x0C9F] = CAST_OP(0x0C9F); + JumpTable[0x0CA7] = CAST_OP(0x0CA7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0800 + i] = CAST_OP(0x0800); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0810 + i] = CAST_OP(0x0810); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0818 + i] = CAST_OP(0x0818); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0820 + i] = CAST_OP(0x0820); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0828 + i] = CAST_OP(0x0828); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0830 + i] = CAST_OP(0x0830); + JumpTable[0x0838] = CAST_OP(0x0838); + JumpTable[0x0839] = CAST_OP(0x0839); + JumpTable[0x083A] = CAST_OP(0x083A); + JumpTable[0x083B] = CAST_OP(0x083B); + JumpTable[0x081F] = CAST_OP(0x081F); + JumpTable[0x0827] = CAST_OP(0x0827); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0840 + i] = CAST_OP(0x0840); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0850 + i] = CAST_OP(0x0850); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0858 + i] = CAST_OP(0x0858); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0860 + i] = CAST_OP(0x0860); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0868 + i] = CAST_OP(0x0868); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0870 + i] = CAST_OP(0x0870); + JumpTable[0x0878] = CAST_OP(0x0878); + JumpTable[0x0879] = CAST_OP(0x0879); + JumpTable[0x085F] = CAST_OP(0x085F); + JumpTable[0x0867] = CAST_OP(0x0867); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0880 + i] = CAST_OP(0x0880); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x0890 + i] = CAST_OP(0x0890); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x0898 + i] = CAST_OP(0x0898); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x08A0 + i] = CAST_OP(0x08A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08A8 + i] = CAST_OP(0x08A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08B0 + i] = CAST_OP(0x08B0); + JumpTable[0x08B8] = CAST_OP(0x08B8); + JumpTable[0x08B9] = CAST_OP(0x08B9); + JumpTable[0x089F] = CAST_OP(0x089F); + JumpTable[0x08A7] = CAST_OP(0x08A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08C0 + i] = CAST_OP(0x08C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08D0 + i] = CAST_OP(0x08D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x08D8 + i] = CAST_OP(0x08D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x08E0 + i] = CAST_OP(0x08E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08E8 + i] = CAST_OP(0x08E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x08F0 + i] = CAST_OP(0x08F0); + JumpTable[0x08F8] = CAST_OP(0x08F8); + JumpTable[0x08F9] = CAST_OP(0x08F9); + JumpTable[0x08DF] = CAST_OP(0x08DF); + JumpTable[0x08E7] = CAST_OP(0x08E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0100 + i + j] = CAST_OP(0x0100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0110 + i + j] = CAST_OP(0x0110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0118 + i + j] = CAST_OP(0x0118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0120 + i + j] = CAST_OP(0x0120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0128 + i + j] = CAST_OP(0x0128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0130 + i + j] = CAST_OP(0x0130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0138 + i] = CAST_OP(0x0138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0139 + i] = CAST_OP(0x0139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x013A + i] = CAST_OP(0x013A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x013B + i] = CAST_OP(0x013B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x013C + i] = CAST_OP(0x013C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x011F + i] = CAST_OP(0x011F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0127 + i] = CAST_OP(0x0127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0140 + i + j] = CAST_OP(0x0140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0150 + i + j] = CAST_OP(0x0150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0158 + i + j] = CAST_OP(0x0158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0160 + i + j] = CAST_OP(0x0160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0168 + i + j] = CAST_OP(0x0168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0170 + i + j] = CAST_OP(0x0170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0178 + i] = CAST_OP(0x0178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0179 + i] = CAST_OP(0x0179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x015F + i] = CAST_OP(0x015F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x0167 + i] = CAST_OP(0x0167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0180 + i + j] = CAST_OP(0x0180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0190 + i + j] = CAST_OP(0x0190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0198 + i + j] = CAST_OP(0x0198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01A0 + i + j] = CAST_OP(0x01A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01A8 + i + j] = CAST_OP(0x01A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01B0 + i + j] = CAST_OP(0x01B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01B8 + i] = CAST_OP(0x01B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01B9 + i] = CAST_OP(0x01B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x019F + i] = CAST_OP(0x019F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01A7 + i] = CAST_OP(0x01A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01C0 + i + j] = CAST_OP(0x01C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01D0 + i + j] = CAST_OP(0x01D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01D8 + i + j] = CAST_OP(0x01D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01E0 + i + j] = CAST_OP(0x01E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01E8 + i + j] = CAST_OP(0x01E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01F0 + i + j] = CAST_OP(0x01F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01F8 + i] = CAST_OP(0x01F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01F9 + i] = CAST_OP(0x01F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01DF + i] = CAST_OP(0x01DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x01E7 + i] = CAST_OP(0x01E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0108 + i + j] = CAST_OP(0x0108); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0148 + i + j] = CAST_OP(0x0148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x0188 + i + j] = CAST_OP(0x0188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x01C8 + i + j] = CAST_OP(0x01C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1000 + i + j] = CAST_OP(0x1000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1080 + i + j] = CAST_OP(0x1080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10C0 + i + j] = CAST_OP(0x10C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1100 + i + j] = CAST_OP(0x1100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1140 + i + j] = CAST_OP(0x1140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1180 + i + j] = CAST_OP(0x1180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x11C0 + i] = CAST_OP(0x11C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x13C0 + i] = CAST_OP(0x13C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1EC0 + i] = CAST_OP(0x1EC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1F00 + i] = CAST_OP(0x1F00); +#if 0 + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1008 + i + j] = CAST_OP(0x1008); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1088 + i + j] = CAST_OP(0x1088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10C8 + i + j] = CAST_OP(0x10C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1108 + i + j] = CAST_OP(0x1108); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1148 + i + j] = CAST_OP(0x1148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1188 + i + j] = CAST_OP(0x1188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x11C8 + i] = CAST_OP(0x11C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x13C8 + i] = CAST_OP(0x13C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1EC8 + i] = CAST_OP(0x1EC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1F08 + i] = CAST_OP(0x1F08); +#endif + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1010 + i + j] = CAST_OP(0x1010); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1090 + i + j] = CAST_OP(0x1090); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10D0 + i + j] = CAST_OP(0x10D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1110 + i + j] = CAST_OP(0x1110); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1150 + i + j] = CAST_OP(0x1150); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1190 + i + j] = CAST_OP(0x1190); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x11D0 + i] = CAST_OP(0x11D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x13D0 + i] = CAST_OP(0x13D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1ED0 + i] = CAST_OP(0x1ED0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1F10 + i] = CAST_OP(0x1F10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1018 + i + j] = CAST_OP(0x1018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1098 + i + j] = CAST_OP(0x1098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10D8 + i + j] = CAST_OP(0x10D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1118 + i + j] = CAST_OP(0x1118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1158 + i + j] = CAST_OP(0x1158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1198 + i + j] = CAST_OP(0x1198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x11D8 + i] = CAST_OP(0x11D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x13D8 + i] = CAST_OP(0x13D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x1ED8 + i] = CAST_OP(0x1ED8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x1F18 + i] = CAST_OP(0x1F18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1020 + i + j] = CAST_OP(0x1020); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x10A0 + i + j] = CAST_OP(0x10A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10E0 + i + j] = CAST_OP(0x10E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1120 + i + j] = CAST_OP(0x1120); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1160 + i + j] = CAST_OP(0x1160); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x11A0 + i + j] = CAST_OP(0x11A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x11E0 + i] = CAST_OP(0x11E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x13E0 + i] = CAST_OP(0x13E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x1EE0 + i] = CAST_OP(0x1EE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x1F20 + i] = CAST_OP(0x1F20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1028 + i + j] = CAST_OP(0x1028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x10A8 + i + j] = CAST_OP(0x10A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10E8 + i + j] = CAST_OP(0x10E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1128 + i + j] = CAST_OP(0x1128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1168 + i + j] = CAST_OP(0x1168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x11A8 + i + j] = CAST_OP(0x11A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x11E8 + i] = CAST_OP(0x11E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x13E8 + i] = CAST_OP(0x13E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1EE8 + i] = CAST_OP(0x1EE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1F28 + i] = CAST_OP(0x1F28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1030 + i + j] = CAST_OP(0x1030); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x10B0 + i + j] = CAST_OP(0x10B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x10F0 + i + j] = CAST_OP(0x10F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x1130 + i + j] = CAST_OP(0x1130); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x1170 + i + j] = CAST_OP(0x1170); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x11B0 + i + j] = CAST_OP(0x11B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x11F0 + i] = CAST_OP(0x11F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x13F0 + i] = CAST_OP(0x13F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1EF0 + i] = CAST_OP(0x1EF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x1F30 + i] = CAST_OP(0x1F30); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1038 + i] = CAST_OP(0x1038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10B8 + i] = CAST_OP(0x10B8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10F8 + i] = CAST_OP(0x10F8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x1138 + i] = CAST_OP(0x1138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1178 + i] = CAST_OP(0x1178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11B8 + i] = CAST_OP(0x11B8); + JumpTable[0x11F8] = CAST_OP(0x11F8); + JumpTable[0x13F8] = CAST_OP(0x13F8); + JumpTable[0x1EF8] = CAST_OP(0x1EF8); + JumpTable[0x1F38] = CAST_OP(0x1F38); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1039 + i] = CAST_OP(0x1039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10B9 + i] = CAST_OP(0x10B9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10F9 + i] = CAST_OP(0x10F9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x1139 + i] = CAST_OP(0x1139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1179 + i] = CAST_OP(0x1179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11B9 + i] = CAST_OP(0x11B9); + JumpTable[0x11F9] = CAST_OP(0x11F9); + JumpTable[0x13F9] = CAST_OP(0x13F9); + JumpTable[0x1EF9] = CAST_OP(0x1EF9); + JumpTable[0x1F39] = CAST_OP(0x1F39); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x103A + i] = CAST_OP(0x103A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10BA + i] = CAST_OP(0x10BA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10FA + i] = CAST_OP(0x10FA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x113A + i] = CAST_OP(0x113A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x117A + i] = CAST_OP(0x117A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11BA + i] = CAST_OP(0x11BA); + JumpTable[0x11FA] = CAST_OP(0x11FA); + JumpTable[0x13FA] = CAST_OP(0x13FA); + JumpTable[0x1EFA] = CAST_OP(0x1EFA); + JumpTable[0x1F3A] = CAST_OP(0x1F3A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x103B + i] = CAST_OP(0x103B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10BB + i] = CAST_OP(0x10BB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10FB + i] = CAST_OP(0x10FB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x113B + i] = CAST_OP(0x113B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x117B + i] = CAST_OP(0x117B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11BB + i] = CAST_OP(0x11BB); + JumpTable[0x11FB] = CAST_OP(0x11FB); + JumpTable[0x13FB] = CAST_OP(0x13FB); + JumpTable[0x1EFB] = CAST_OP(0x1EFB); + JumpTable[0x1F3B] = CAST_OP(0x1F3B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x103C + i] = CAST_OP(0x103C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10BC + i] = CAST_OP(0x10BC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10FC + i] = CAST_OP(0x10FC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x113C + i] = CAST_OP(0x113C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x117C + i] = CAST_OP(0x117C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11BC + i] = CAST_OP(0x11BC); + JumpTable[0x11FC] = CAST_OP(0x11FC); + JumpTable[0x13FC] = CAST_OP(0x13FC); + JumpTable[0x1EFC] = CAST_OP(0x1EFC); + JumpTable[0x1F3C] = CAST_OP(0x1F3C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x101F + i] = CAST_OP(0x101F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x109F + i] = CAST_OP(0x109F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10DF + i] = CAST_OP(0x10DF); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x111F + i] = CAST_OP(0x111F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x115F + i] = CAST_OP(0x115F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x119F + i] = CAST_OP(0x119F); + JumpTable[0x11DF] = CAST_OP(0x11DF); + JumpTable[0x13DF] = CAST_OP(0x13DF); + JumpTable[0x1EDF] = CAST_OP(0x1EDF); + JumpTable[0x1F1F] = CAST_OP(0x1F1F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1027 + i] = CAST_OP(0x1027); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x10A7 + i] = CAST_OP(0x10A7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x10E7 + i] = CAST_OP(0x10E7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x1127 + i] = CAST_OP(0x1127); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x1167 + i] = CAST_OP(0x1167); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x11A7 + i] = CAST_OP(0x11A7); + JumpTable[0x11E7] = CAST_OP(0x11E7); + JumpTable[0x13E7] = CAST_OP(0x13E7); + JumpTable[0x1EE7] = CAST_OP(0x1EE7); + JumpTable[0x1F27] = CAST_OP(0x1F27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2000 + i + j] = CAST_OP(0x2000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2080 + i + j] = CAST_OP(0x2080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20C0 + i + j] = CAST_OP(0x20C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2100 + i + j] = CAST_OP(0x2100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2140 + i + j] = CAST_OP(0x2140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2180 + i + j] = CAST_OP(0x2180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x21C0 + i] = CAST_OP(0x21C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x23C0 + i] = CAST_OP(0x23C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2EC0 + i] = CAST_OP(0x2EC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2F00 + i] = CAST_OP(0x2F00); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2008 + i + j] = CAST_OP(0x2008); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2088 + i + j] = CAST_OP(0x2088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20C8 + i + j] = CAST_OP(0x20C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2108 + i + j] = CAST_OP(0x2108); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2148 + i + j] = CAST_OP(0x2148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2188 + i + j] = CAST_OP(0x2188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x21C8 + i] = CAST_OP(0x21C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x23C8 + i] = CAST_OP(0x23C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2EC8 + i] = CAST_OP(0x2EC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2F08 + i] = CAST_OP(0x2F08); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2010 + i + j] = CAST_OP(0x2010); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2090 + i + j] = CAST_OP(0x2090); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20D0 + i + j] = CAST_OP(0x20D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2110 + i + j] = CAST_OP(0x2110); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2150 + i + j] = CAST_OP(0x2150); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2190 + i + j] = CAST_OP(0x2190); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x21D0 + i] = CAST_OP(0x21D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x23D0 + i] = CAST_OP(0x23D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2ED0 + i] = CAST_OP(0x2ED0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2F10 + i] = CAST_OP(0x2F10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2018 + i + j] = CAST_OP(0x2018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2098 + i + j] = CAST_OP(0x2098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20D8 + i + j] = CAST_OP(0x20D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2118 + i + j] = CAST_OP(0x2118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2158 + i + j] = CAST_OP(0x2158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2198 + i + j] = CAST_OP(0x2198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x21D8 + i] = CAST_OP(0x21D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x23D8 + i] = CAST_OP(0x23D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x2ED8 + i] = CAST_OP(0x2ED8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x2F18 + i] = CAST_OP(0x2F18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2020 + i + j] = CAST_OP(0x2020); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x20A0 + i + j] = CAST_OP(0x20A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20E0 + i + j] = CAST_OP(0x20E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2120 + i + j] = CAST_OP(0x2120); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2160 + i + j] = CAST_OP(0x2160); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x21A0 + i + j] = CAST_OP(0x21A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x21E0 + i] = CAST_OP(0x21E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x23E0 + i] = CAST_OP(0x23E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x2EE0 + i] = CAST_OP(0x2EE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x2F20 + i] = CAST_OP(0x2F20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2028 + i + j] = CAST_OP(0x2028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x20A8 + i + j] = CAST_OP(0x20A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20E8 + i + j] = CAST_OP(0x20E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2128 + i + j] = CAST_OP(0x2128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2168 + i + j] = CAST_OP(0x2168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x21A8 + i + j] = CAST_OP(0x21A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x21E8 + i] = CAST_OP(0x21E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x23E8 + i] = CAST_OP(0x23E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2EE8 + i] = CAST_OP(0x2EE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2F28 + i] = CAST_OP(0x2F28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2030 + i + j] = CAST_OP(0x2030); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x20B0 + i + j] = CAST_OP(0x20B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x20F0 + i + j] = CAST_OP(0x20F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x2130 + i + j] = CAST_OP(0x2130); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2170 + i + j] = CAST_OP(0x2170); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x21B0 + i + j] = CAST_OP(0x21B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x21F0 + i] = CAST_OP(0x21F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x23F0 + i] = CAST_OP(0x23F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2EF0 + i] = CAST_OP(0x2EF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x2F30 + i] = CAST_OP(0x2F30); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2038 + i] = CAST_OP(0x2038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20B8 + i] = CAST_OP(0x20B8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20F8 + i] = CAST_OP(0x20F8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x2138 + i] = CAST_OP(0x2138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2178 + i] = CAST_OP(0x2178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21B8 + i] = CAST_OP(0x21B8); + JumpTable[0x21F8] = CAST_OP(0x21F8); + JumpTable[0x23F8] = CAST_OP(0x23F8); + JumpTable[0x2EF8] = CAST_OP(0x2EF8); + JumpTable[0x2F38] = CAST_OP(0x2F38); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2039 + i] = CAST_OP(0x2039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20B9 + i] = CAST_OP(0x20B9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20F9 + i] = CAST_OP(0x20F9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x2139 + i] = CAST_OP(0x2139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2179 + i] = CAST_OP(0x2179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21B9 + i] = CAST_OP(0x21B9); + JumpTable[0x21F9] = CAST_OP(0x21F9); + JumpTable[0x23F9] = CAST_OP(0x23F9); + JumpTable[0x2EF9] = CAST_OP(0x2EF9); + JumpTable[0x2F39] = CAST_OP(0x2F39); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x203A + i] = CAST_OP(0x203A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20BA + i] = CAST_OP(0x20BA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20FA + i] = CAST_OP(0x20FA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x213A + i] = CAST_OP(0x213A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x217A + i] = CAST_OP(0x217A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21BA + i] = CAST_OP(0x21BA); + JumpTable[0x21FA] = CAST_OP(0x21FA); + JumpTable[0x23FA] = CAST_OP(0x23FA); + JumpTable[0x2EFA] = CAST_OP(0x2EFA); + JumpTable[0x2F3A] = CAST_OP(0x2F3A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x203B + i] = CAST_OP(0x203B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20BB + i] = CAST_OP(0x20BB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20FB + i] = CAST_OP(0x20FB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x213B + i] = CAST_OP(0x213B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x217B + i] = CAST_OP(0x217B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21BB + i] = CAST_OP(0x21BB); + JumpTable[0x21FB] = CAST_OP(0x21FB); + JumpTable[0x23FB] = CAST_OP(0x23FB); + JumpTable[0x2EFB] = CAST_OP(0x2EFB); + JumpTable[0x2F3B] = CAST_OP(0x2F3B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x203C + i] = CAST_OP(0x203C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20BC + i] = CAST_OP(0x20BC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20FC + i] = CAST_OP(0x20FC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x213C + i] = CAST_OP(0x213C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x217C + i] = CAST_OP(0x217C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21BC + i] = CAST_OP(0x21BC); + JumpTable[0x21FC] = CAST_OP(0x21FC); + JumpTable[0x23FC] = CAST_OP(0x23FC); + JumpTable[0x2EFC] = CAST_OP(0x2EFC); + JumpTable[0x2F3C] = CAST_OP(0x2F3C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x201F + i] = CAST_OP(0x201F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x209F + i] = CAST_OP(0x209F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20DF + i] = CAST_OP(0x20DF); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x211F + i] = CAST_OP(0x211F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x215F + i] = CAST_OP(0x215F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x219F + i] = CAST_OP(0x219F); + JumpTable[0x21DF] = CAST_OP(0x21DF); + JumpTable[0x23DF] = CAST_OP(0x23DF); + JumpTable[0x2EDF] = CAST_OP(0x2EDF); + JumpTable[0x2F1F] = CAST_OP(0x2F1F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2027 + i] = CAST_OP(0x2027); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x20A7 + i] = CAST_OP(0x20A7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x20E7 + i] = CAST_OP(0x20E7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x2127 + i] = CAST_OP(0x2127); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2167 + i] = CAST_OP(0x2167); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x21A7 + i] = CAST_OP(0x21A7); + JumpTable[0x21E7] = CAST_OP(0x21E7); + JumpTable[0x23E7] = CAST_OP(0x23E7); + JumpTable[0x2EE7] = CAST_OP(0x2EE7); + JumpTable[0x2F27] = CAST_OP(0x2F27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3000 + i + j] = CAST_OP(0x3000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3080 + i + j] = CAST_OP(0x3080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30C0 + i + j] = CAST_OP(0x30C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3100 + i + j] = CAST_OP(0x3100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3140 + i + j] = CAST_OP(0x3140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3180 + i + j] = CAST_OP(0x3180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x31C0 + i] = CAST_OP(0x31C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x33C0 + i] = CAST_OP(0x33C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3EC0 + i] = CAST_OP(0x3EC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3F00 + i] = CAST_OP(0x3F00); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3008 + i + j] = CAST_OP(0x3008); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3088 + i + j] = CAST_OP(0x3088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30C8 + i + j] = CAST_OP(0x30C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3108 + i + j] = CAST_OP(0x3108); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3148 + i + j] = CAST_OP(0x3148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3188 + i + j] = CAST_OP(0x3188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x31C8 + i] = CAST_OP(0x31C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x33C8 + i] = CAST_OP(0x33C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3EC8 + i] = CAST_OP(0x3EC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3F08 + i] = CAST_OP(0x3F08); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3010 + i + j] = CAST_OP(0x3010); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3090 + i + j] = CAST_OP(0x3090); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30D0 + i + j] = CAST_OP(0x30D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3110 + i + j] = CAST_OP(0x3110); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3150 + i + j] = CAST_OP(0x3150); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3190 + i + j] = CAST_OP(0x3190); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x31D0 + i] = CAST_OP(0x31D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x33D0 + i] = CAST_OP(0x33D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3ED0 + i] = CAST_OP(0x3ED0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3F10 + i] = CAST_OP(0x3F10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3018 + i + j] = CAST_OP(0x3018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3098 + i + j] = CAST_OP(0x3098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30D8 + i + j] = CAST_OP(0x30D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3118 + i + j] = CAST_OP(0x3118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3158 + i + j] = CAST_OP(0x3158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3198 + i + j] = CAST_OP(0x3198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x31D8 + i] = CAST_OP(0x31D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x33D8 + i] = CAST_OP(0x33D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x3ED8 + i] = CAST_OP(0x3ED8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x3F18 + i] = CAST_OP(0x3F18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3020 + i + j] = CAST_OP(0x3020); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x30A0 + i + j] = CAST_OP(0x30A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30E0 + i + j] = CAST_OP(0x30E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3120 + i + j] = CAST_OP(0x3120); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3160 + i + j] = CAST_OP(0x3160); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x31A0 + i + j] = CAST_OP(0x31A0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x31E0 + i] = CAST_OP(0x31E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x33E0 + i] = CAST_OP(0x33E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x3EE0 + i] = CAST_OP(0x3EE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x3F20 + i] = CAST_OP(0x3F20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3028 + i + j] = CAST_OP(0x3028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x30A8 + i + j] = CAST_OP(0x30A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30E8 + i + j] = CAST_OP(0x30E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3128 + i + j] = CAST_OP(0x3128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3168 + i + j] = CAST_OP(0x3168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x31A8 + i + j] = CAST_OP(0x31A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x31E8 + i] = CAST_OP(0x31E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x33E8 + i] = CAST_OP(0x33E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3EE8 + i] = CAST_OP(0x3EE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3F28 + i] = CAST_OP(0x3F28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3030 + i + j] = CAST_OP(0x3030); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x30B0 + i + j] = CAST_OP(0x30B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x30F0 + i + j] = CAST_OP(0x30F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x3130 + i + j] = CAST_OP(0x3130); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3170 + i + j] = CAST_OP(0x3170); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x31B0 + i + j] = CAST_OP(0x31B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x31F0 + i] = CAST_OP(0x31F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x33F0 + i] = CAST_OP(0x33F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3EF0 + i] = CAST_OP(0x3EF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x3F30 + i] = CAST_OP(0x3F30); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3038 + i] = CAST_OP(0x3038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30B8 + i] = CAST_OP(0x30B8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30F8 + i] = CAST_OP(0x30F8); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x3138 + i] = CAST_OP(0x3138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3178 + i] = CAST_OP(0x3178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31B8 + i] = CAST_OP(0x31B8); + JumpTable[0x31F8] = CAST_OP(0x31F8); + JumpTable[0x33F8] = CAST_OP(0x33F8); + JumpTable[0x3EF8] = CAST_OP(0x3EF8); + JumpTable[0x3F38] = CAST_OP(0x3F38); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3039 + i] = CAST_OP(0x3039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30B9 + i] = CAST_OP(0x30B9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30F9 + i] = CAST_OP(0x30F9); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x3139 + i] = CAST_OP(0x3139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3179 + i] = CAST_OP(0x3179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31B9 + i] = CAST_OP(0x31B9); + JumpTable[0x31F9] = CAST_OP(0x31F9); + JumpTable[0x33F9] = CAST_OP(0x33F9); + JumpTable[0x3EF9] = CAST_OP(0x3EF9); + JumpTable[0x3F39] = CAST_OP(0x3F39); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x303A + i] = CAST_OP(0x303A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30BA + i] = CAST_OP(0x30BA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30FA + i] = CAST_OP(0x30FA); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x313A + i] = CAST_OP(0x313A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x317A + i] = CAST_OP(0x317A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31BA + i] = CAST_OP(0x31BA); + JumpTable[0x31FA] = CAST_OP(0x31FA); + JumpTable[0x33FA] = CAST_OP(0x33FA); + JumpTable[0x3EFA] = CAST_OP(0x3EFA); + JumpTable[0x3F3A] = CAST_OP(0x3F3A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x303B + i] = CAST_OP(0x303B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30BB + i] = CAST_OP(0x30BB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30FB + i] = CAST_OP(0x30FB); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x313B + i] = CAST_OP(0x313B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x317B + i] = CAST_OP(0x317B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31BB + i] = CAST_OP(0x31BB); + JumpTable[0x31FB] = CAST_OP(0x31FB); + JumpTable[0x33FB] = CAST_OP(0x33FB); + JumpTable[0x3EFB] = CAST_OP(0x3EFB); + JumpTable[0x3F3B] = CAST_OP(0x3F3B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x303C + i] = CAST_OP(0x303C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30BC + i] = CAST_OP(0x30BC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30FC + i] = CAST_OP(0x30FC); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x313C + i] = CAST_OP(0x313C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x317C + i] = CAST_OP(0x317C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31BC + i] = CAST_OP(0x31BC); + JumpTable[0x31FC] = CAST_OP(0x31FC); + JumpTable[0x33FC] = CAST_OP(0x33FC); + JumpTable[0x3EFC] = CAST_OP(0x3EFC); + JumpTable[0x3F3C] = CAST_OP(0x3F3C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x301F + i] = CAST_OP(0x301F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x309F + i] = CAST_OP(0x309F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30DF + i] = CAST_OP(0x30DF); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x311F + i] = CAST_OP(0x311F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x315F + i] = CAST_OP(0x315F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x319F + i] = CAST_OP(0x319F); + JumpTable[0x31DF] = CAST_OP(0x31DF); + JumpTable[0x33DF] = CAST_OP(0x33DF); + JumpTable[0x3EDF] = CAST_OP(0x3EDF); + JumpTable[0x3F1F] = CAST_OP(0x3F1F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3027 + i] = CAST_OP(0x3027); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x30A7 + i] = CAST_OP(0x30A7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x30E7 + i] = CAST_OP(0x30E7); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x3127 + i] = CAST_OP(0x3127); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3167 + i] = CAST_OP(0x3167); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x31A7 + i] = CAST_OP(0x31A7); + JumpTable[0x31E7] = CAST_OP(0x31E7); + JumpTable[0x33E7] = CAST_OP(0x33E7); + JumpTable[0x3EE7] = CAST_OP(0x3EE7); + JumpTable[0x3F27] = CAST_OP(0x3F27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2040 + i + j] = CAST_OP(0x2040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2048 + i + j] = CAST_OP(0x2048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2050 + i + j] = CAST_OP(0x2050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2058 + i + j] = CAST_OP(0x2058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2060 + i + j] = CAST_OP(0x2060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2068 + i + j] = CAST_OP(0x2068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x2070 + i + j] = CAST_OP(0x2070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2078 + i] = CAST_OP(0x2078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2079 + i] = CAST_OP(0x2079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x207A + i] = CAST_OP(0x207A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x207B + i] = CAST_OP(0x207B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x207C + i] = CAST_OP(0x207C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x205F + i] = CAST_OP(0x205F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x2067 + i] = CAST_OP(0x2067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3040 + i + j] = CAST_OP(0x3040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3048 + i + j] = CAST_OP(0x3048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3050 + i + j] = CAST_OP(0x3050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3058 + i + j] = CAST_OP(0x3058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3060 + i + j] = CAST_OP(0x3060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3068 + i + j] = CAST_OP(0x3068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x3070 + i + j] = CAST_OP(0x3070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3078 + i] = CAST_OP(0x3078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3079 + i] = CAST_OP(0x3079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x307A + i] = CAST_OP(0x307A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x307B + i] = CAST_OP(0x307B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x307C + i] = CAST_OP(0x307C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x305F + i] = CAST_OP(0x305F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x3067 + i] = CAST_OP(0x3067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4000 + i] = CAST_OP(0x4000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4010 + i] = CAST_OP(0x4010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4018 + i] = CAST_OP(0x4018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4020 + i] = CAST_OP(0x4020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4028 + i] = CAST_OP(0x4028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4030 + i] = CAST_OP(0x4030); + JumpTable[0x4038] = CAST_OP(0x4038); + JumpTable[0x4039] = CAST_OP(0x4039); + JumpTable[0x401F] = CAST_OP(0x401F); + JumpTable[0x4027] = CAST_OP(0x4027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4040 + i] = CAST_OP(0x4040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4050 + i] = CAST_OP(0x4050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4058 + i] = CAST_OP(0x4058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4060 + i] = CAST_OP(0x4060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4068 + i] = CAST_OP(0x4068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4070 + i] = CAST_OP(0x4070); + JumpTable[0x4078] = CAST_OP(0x4078); + JumpTable[0x4079] = CAST_OP(0x4079); + JumpTable[0x405F] = CAST_OP(0x405F); + JumpTable[0x4067] = CAST_OP(0x4067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4080 + i] = CAST_OP(0x4080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4090 + i] = CAST_OP(0x4090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4098 + i] = CAST_OP(0x4098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x40A0 + i] = CAST_OP(0x40A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40A8 + i] = CAST_OP(0x40A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40B0 + i] = CAST_OP(0x40B0); + JumpTable[0x40B8] = CAST_OP(0x40B8); + JumpTable[0x40B9] = CAST_OP(0x40B9); + JumpTable[0x409F] = CAST_OP(0x409F); + JumpTable[0x40A7] = CAST_OP(0x40A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4200 + i] = CAST_OP(0x4200); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4210 + i] = CAST_OP(0x4210); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4218 + i] = CAST_OP(0x4218); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4220 + i] = CAST_OP(0x4220); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4228 + i] = CAST_OP(0x4228); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4230 + i] = CAST_OP(0x4230); + JumpTable[0x4238] = CAST_OP(0x4238); + JumpTable[0x4239] = CAST_OP(0x4239); + JumpTable[0x421F] = CAST_OP(0x421F); + JumpTable[0x4227] = CAST_OP(0x4227); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4240 + i] = CAST_OP(0x4240); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4250 + i] = CAST_OP(0x4250); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4258 + i] = CAST_OP(0x4258); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4260 + i] = CAST_OP(0x4260); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4268 + i] = CAST_OP(0x4268); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4270 + i] = CAST_OP(0x4270); + JumpTable[0x4278] = CAST_OP(0x4278); + JumpTable[0x4279] = CAST_OP(0x4279); + JumpTable[0x425F] = CAST_OP(0x425F); + JumpTable[0x4267] = CAST_OP(0x4267); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4280 + i] = CAST_OP(0x4280); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4290 + i] = CAST_OP(0x4290); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4298 + i] = CAST_OP(0x4298); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x42A0 + i] = CAST_OP(0x42A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x42A8 + i] = CAST_OP(0x42A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x42B0 + i] = CAST_OP(0x42B0); + JumpTable[0x42B8] = CAST_OP(0x42B8); + JumpTable[0x42B9] = CAST_OP(0x42B9); + JumpTable[0x429F] = CAST_OP(0x429F); + JumpTable[0x42A7] = CAST_OP(0x42A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4400 + i] = CAST_OP(0x4400); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4410 + i] = CAST_OP(0x4410); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4418 + i] = CAST_OP(0x4418); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4420 + i] = CAST_OP(0x4420); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4428 + i] = CAST_OP(0x4428); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4430 + i] = CAST_OP(0x4430); + JumpTable[0x4438] = CAST_OP(0x4438); + JumpTable[0x4439] = CAST_OP(0x4439); + JumpTable[0x441F] = CAST_OP(0x441F); + JumpTable[0x4427] = CAST_OP(0x4427); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4440 + i] = CAST_OP(0x4440); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4450 + i] = CAST_OP(0x4450); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4458 + i] = CAST_OP(0x4458); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4460 + i] = CAST_OP(0x4460); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4468 + i] = CAST_OP(0x4468); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4470 + i] = CAST_OP(0x4470); + JumpTable[0x4478] = CAST_OP(0x4478); + JumpTable[0x4479] = CAST_OP(0x4479); + JumpTable[0x445F] = CAST_OP(0x445F); + JumpTable[0x4467] = CAST_OP(0x4467); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4480 + i] = CAST_OP(0x4480); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4490 + i] = CAST_OP(0x4490); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4498 + i] = CAST_OP(0x4498); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x44A0 + i] = CAST_OP(0x44A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44A8 + i] = CAST_OP(0x44A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44B0 + i] = CAST_OP(0x44B0); + JumpTable[0x44B8] = CAST_OP(0x44B8); + JumpTable[0x44B9] = CAST_OP(0x44B9); + JumpTable[0x449F] = CAST_OP(0x449F); + JumpTable[0x44A7] = CAST_OP(0x44A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4600 + i] = CAST_OP(0x4600); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4610 + i] = CAST_OP(0x4610); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4618 + i] = CAST_OP(0x4618); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4620 + i] = CAST_OP(0x4620); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4628 + i] = CAST_OP(0x4628); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4630 + i] = CAST_OP(0x4630); + JumpTable[0x4638] = CAST_OP(0x4638); + JumpTable[0x4639] = CAST_OP(0x4639); + JumpTable[0x461F] = CAST_OP(0x461F); + JumpTable[0x4627] = CAST_OP(0x4627); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4640 + i] = CAST_OP(0x4640); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4650 + i] = CAST_OP(0x4650); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4658 + i] = CAST_OP(0x4658); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4660 + i] = CAST_OP(0x4660); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4668 + i] = CAST_OP(0x4668); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4670 + i] = CAST_OP(0x4670); + JumpTable[0x4678] = CAST_OP(0x4678); + JumpTable[0x4679] = CAST_OP(0x4679); + JumpTable[0x465F] = CAST_OP(0x465F); + JumpTable[0x4667] = CAST_OP(0x4667); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4680 + i] = CAST_OP(0x4680); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4690 + i] = CAST_OP(0x4690); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4698 + i] = CAST_OP(0x4698); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x46A0 + i] = CAST_OP(0x46A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46A8 + i] = CAST_OP(0x46A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46B0 + i] = CAST_OP(0x46B0); + JumpTable[0x46B8] = CAST_OP(0x46B8); + JumpTable[0x46B9] = CAST_OP(0x46B9); + JumpTable[0x469F] = CAST_OP(0x469F); + JumpTable[0x46A7] = CAST_OP(0x46A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40C0 + i] = CAST_OP(0x40C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40D0 + i] = CAST_OP(0x40D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x40D8 + i] = CAST_OP(0x40D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x40E0 + i] = CAST_OP(0x40E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40E8 + i] = CAST_OP(0x40E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x40F0 + i] = CAST_OP(0x40F0); + JumpTable[0x40F8] = CAST_OP(0x40F8); + JumpTable[0x40F9] = CAST_OP(0x40F9); + JumpTable[0x40DF] = CAST_OP(0x40DF); + JumpTable[0x40E7] = CAST_OP(0x40E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44C0 + i] = CAST_OP(0x44C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44D0 + i] = CAST_OP(0x44D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x44D8 + i] = CAST_OP(0x44D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x44E0 + i] = CAST_OP(0x44E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44E8 + i] = CAST_OP(0x44E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x44F0 + i] = CAST_OP(0x44F0); + JumpTable[0x44F8] = CAST_OP(0x44F8); + JumpTable[0x44F9] = CAST_OP(0x44F9); + JumpTable[0x44FA] = CAST_OP(0x44FA); + JumpTable[0x44FB] = CAST_OP(0x44FB); + JumpTable[0x44FC] = CAST_OP(0x44FC); + JumpTable[0x44DF] = CAST_OP(0x44DF); + JumpTable[0x44E7] = CAST_OP(0x44E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46C0 + i] = CAST_OP(0x46C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46D0 + i] = CAST_OP(0x46D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x46D8 + i] = CAST_OP(0x46D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x46E0 + i] = CAST_OP(0x46E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46E8 + i] = CAST_OP(0x46E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x46F0 + i] = CAST_OP(0x46F0); + JumpTable[0x46F8] = CAST_OP(0x46F8); + JumpTable[0x46F9] = CAST_OP(0x46F9); + JumpTable[0x46FA] = CAST_OP(0x46FA); + JumpTable[0x46FB] = CAST_OP(0x46FB); + JumpTable[0x46FC] = CAST_OP(0x46FC); + JumpTable[0x46DF] = CAST_OP(0x46DF); + JumpTable[0x46E7] = CAST_OP(0x46E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4800 + i] = CAST_OP(0x4800); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4810 + i] = CAST_OP(0x4810); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4818 + i] = CAST_OP(0x4818); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4820 + i] = CAST_OP(0x4820); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4828 + i] = CAST_OP(0x4828); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4830 + i] = CAST_OP(0x4830); + JumpTable[0x4838] = CAST_OP(0x4838); + JumpTable[0x4839] = CAST_OP(0x4839); + JumpTable[0x481F] = CAST_OP(0x481F); + JumpTable[0x4827] = CAST_OP(0x4827); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4850 + i] = CAST_OP(0x4850); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4868 + i] = CAST_OP(0x4868); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4870 + i] = CAST_OP(0x4870); + JumpTable[0x4878] = CAST_OP(0x4878); + JumpTable[0x4879] = CAST_OP(0x4879); + JumpTable[0x487A] = CAST_OP(0x487A); + JumpTable[0x487B] = CAST_OP(0x487B); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4840 + i] = CAST_OP(0x4840); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4890 + i] = CAST_OP(0x4890); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x48A0 + i] = CAST_OP(0x48A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48A8 + i] = CAST_OP(0x48A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48B0 + i] = CAST_OP(0x48B0); + JumpTable[0x48B8] = CAST_OP(0x48B8); + JumpTable[0x48B9] = CAST_OP(0x48B9); + JumpTable[0x48A7] = CAST_OP(0x48A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48D0 + i] = CAST_OP(0x48D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x48E0 + i] = CAST_OP(0x48E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48E8 + i] = CAST_OP(0x48E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48F0 + i] = CAST_OP(0x48F0); + JumpTable[0x48F8] = CAST_OP(0x48F8); + JumpTable[0x48F9] = CAST_OP(0x48F9); + JumpTable[0x48E7] = CAST_OP(0x48E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4880 + i] = CAST_OP(0x4880); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x48C0 + i] = CAST_OP(0x48C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A00 + i] = CAST_OP(0x4A00); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A10 + i] = CAST_OP(0x4A10); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4A18 + i] = CAST_OP(0x4A18); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4A20 + i] = CAST_OP(0x4A20); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A28 + i] = CAST_OP(0x4A28); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A30 + i] = CAST_OP(0x4A30); + JumpTable[0x4A38] = CAST_OP(0x4A38); + JumpTable[0x4A39] = CAST_OP(0x4A39); + JumpTable[0x4A1F] = CAST_OP(0x4A1F); + JumpTable[0x4A27] = CAST_OP(0x4A27); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A40 + i] = CAST_OP(0x4A40); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A50 + i] = CAST_OP(0x4A50); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4A58 + i] = CAST_OP(0x4A58); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4A60 + i] = CAST_OP(0x4A60); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A68 + i] = CAST_OP(0x4A68); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A70 + i] = CAST_OP(0x4A70); + JumpTable[0x4A78] = CAST_OP(0x4A78); + JumpTable[0x4A79] = CAST_OP(0x4A79); + JumpTable[0x4A5F] = CAST_OP(0x4A5F); + JumpTable[0x4A67] = CAST_OP(0x4A67); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A80 + i] = CAST_OP(0x4A80); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4A90 + i] = CAST_OP(0x4A90); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4A98 + i] = CAST_OP(0x4A98); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4AA0 + i] = CAST_OP(0x4AA0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AA8 + i] = CAST_OP(0x4AA8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AB0 + i] = CAST_OP(0x4AB0); + JumpTable[0x4AB8] = CAST_OP(0x4AB8); + JumpTable[0x4AB9] = CAST_OP(0x4AB9); + JumpTable[0x4A9F] = CAST_OP(0x4A9F); + JumpTable[0x4AA7] = CAST_OP(0x4AA7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AC0 + i] = CAST_OP(0x4AC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AD0 + i] = CAST_OP(0x4AD0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4AD8 + i] = CAST_OP(0x4AD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4AE0 + i] = CAST_OP(0x4AE0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AE8 + i] = CAST_OP(0x4AE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4AF0 + i] = CAST_OP(0x4AF0); + JumpTable[0x4AF8] = CAST_OP(0x4AF8); + JumpTable[0x4AF9] = CAST_OP(0x4AF9); + JumpTable[0x4ADF] = CAST_OP(0x4ADF); + JumpTable[0x4AE7] = CAST_OP(0x4AE7); + JumpTable[0x4AFC] = CAST_OP(0x4AFC); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4C90 + i] = CAST_OP(0x4C90); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4C98 + i] = CAST_OP(0x4C98); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4CA8 + i] = CAST_OP(0x4CA8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4CB0 + i] = CAST_OP(0x4CB0); + JumpTable[0x4CB8] = CAST_OP(0x4CB8); + JumpTable[0x4CB9] = CAST_OP(0x4CB9); + JumpTable[0x4CBA] = CAST_OP(0x4CBA); + JumpTable[0x4CBB] = CAST_OP(0x4CBB); + JumpTable[0x4C9F] = CAST_OP(0x4C9F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4CD0 + i] = CAST_OP(0x4CD0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x4CD8 + i] = CAST_OP(0x4CD8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4CE8 + i] = CAST_OP(0x4CE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4CF0 + i] = CAST_OP(0x4CF0); + JumpTable[0x4CF8] = CAST_OP(0x4CF8); + JumpTable[0x4CF9] = CAST_OP(0x4CF9); + JumpTable[0x4CFA] = CAST_OP(0x4CFA); + JumpTable[0x4CFB] = CAST_OP(0x4CFB); + JumpTable[0x4CDF] = CAST_OP(0x4CDF); + for(i = 0x0000; i <= 0x000F; i += 0x0001) + JumpTable[0x4E40 + i] = CAST_OP(0x4E40); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4E50 + i] = CAST_OP(0x4E50); + JumpTable[0x4E57] = CAST_OP(0x4E57); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4E58 + i] = CAST_OP(0x4E58); + JumpTable[0x4E5F] = CAST_OP(0x4E5F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4E60 + i] = CAST_OP(0x4E60); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4E68 + i] = CAST_OP(0x4E68); + JumpTable[0x4E70] = CAST_OP(0x4E70); + JumpTable[0x4E71] = CAST_OP(0x4E71); + JumpTable[0x4E72] = CAST_OP(0x4E72); + JumpTable[0x4E73] = CAST_OP(0x4E73); + JumpTable[0x4E75] = CAST_OP(0x4E75); + JumpTable[0x4E76] = CAST_OP(0x4E76); + JumpTable[0x4E77] = CAST_OP(0x4E77); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4E90 + i] = CAST_OP(0x4E90); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4EA8 + i] = CAST_OP(0x4EA8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4EB0 + i] = CAST_OP(0x4EB0); + JumpTable[0x4EB8] = CAST_OP(0x4EB8); + JumpTable[0x4EB9] = CAST_OP(0x4EB9); + JumpTable[0x4EBA] = CAST_OP(0x4EBA); + JumpTable[0x4EBB] = CAST_OP(0x4EBB); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4ED0 + i] = CAST_OP(0x4ED0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4EE8 + i] = CAST_OP(0x4EE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x4EF0 + i] = CAST_OP(0x4EF0); + JumpTable[0x4EF8] = CAST_OP(0x4EF8); + JumpTable[0x4EF9] = CAST_OP(0x4EF9); + JumpTable[0x4EFA] = CAST_OP(0x4EFA); + JumpTable[0x4EFB] = CAST_OP(0x4EFB); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x4180 + i + j] = CAST_OP(0x4180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x4190 + i + j] = CAST_OP(0x4190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x4198 + i + j] = CAST_OP(0x4198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41A0 + i + j] = CAST_OP(0x41A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41A8 + i + j] = CAST_OP(0x41A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41B0 + i + j] = CAST_OP(0x41B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41B8 + i] = CAST_OP(0x41B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41B9 + i] = CAST_OP(0x41B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41BA + i] = CAST_OP(0x41BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41BB + i] = CAST_OP(0x41BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41BC + i] = CAST_OP(0x41BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x419F + i] = CAST_OP(0x419F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41A7 + i] = CAST_OP(0x41A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41D0 + i + j] = CAST_OP(0x41D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41E8 + i + j] = CAST_OP(0x41E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x41F0 + i + j] = CAST_OP(0x41F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41F8 + i] = CAST_OP(0x41F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41F9 + i] = CAST_OP(0x41F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41FA + i] = CAST_OP(0x41FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x41FB + i] = CAST_OP(0x41FB); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x50C0 + i] = CAST_OP(0x50C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x51C0 + i] = CAST_OP(0x51C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x52C0 + i] = CAST_OP(0x52C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x53C0 + i] = CAST_OP(0x53C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x54C0 + i] = CAST_OP(0x54C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x55C0 + i] = CAST_OP(0x55C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x56C0 + i] = CAST_OP(0x56C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x57C0 + i] = CAST_OP(0x57C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x58C0 + i] = CAST_OP(0x58C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x59C0 + i] = CAST_OP(0x59C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5AC0 + i] = CAST_OP(0x5AC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5BC0 + i] = CAST_OP(0x5BC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5CC0 + i] = CAST_OP(0x5CC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5DC0 + i] = CAST_OP(0x5DC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5EC0 + i] = CAST_OP(0x5EC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5FC0 + i] = CAST_OP(0x5FC0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x50D0 + i] = CAST_OP(0x50D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x51D0 + i] = CAST_OP(0x51D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x52D0 + i] = CAST_OP(0x52D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x53D0 + i] = CAST_OP(0x53D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x54D0 + i] = CAST_OP(0x54D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x55D0 + i] = CAST_OP(0x55D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x56D0 + i] = CAST_OP(0x56D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x57D0 + i] = CAST_OP(0x57D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x58D0 + i] = CAST_OP(0x58D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x59D0 + i] = CAST_OP(0x59D0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5AD0 + i] = CAST_OP(0x5AD0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5BD0 + i] = CAST_OP(0x5BD0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5CD0 + i] = CAST_OP(0x5CD0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5DD0 + i] = CAST_OP(0x5DD0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5ED0 + i] = CAST_OP(0x5ED0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5FD0 + i] = CAST_OP(0x5FD0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x50D8 + i] = CAST_OP(0x50D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x51D8 + i] = CAST_OP(0x51D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x52D8 + i] = CAST_OP(0x52D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x53D8 + i] = CAST_OP(0x53D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x54D8 + i] = CAST_OP(0x54D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x55D8 + i] = CAST_OP(0x55D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x56D8 + i] = CAST_OP(0x56D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x57D8 + i] = CAST_OP(0x57D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x58D8 + i] = CAST_OP(0x58D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x59D8 + i] = CAST_OP(0x59D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5AD8 + i] = CAST_OP(0x5AD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5BD8 + i] = CAST_OP(0x5BD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5CD8 + i] = CAST_OP(0x5CD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5DD8 + i] = CAST_OP(0x5DD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5ED8 + i] = CAST_OP(0x5ED8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5FD8 + i] = CAST_OP(0x5FD8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x50E0 + i] = CAST_OP(0x50E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x51E0 + i] = CAST_OP(0x51E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x52E0 + i] = CAST_OP(0x52E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x53E0 + i] = CAST_OP(0x53E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x54E0 + i] = CAST_OP(0x54E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x55E0 + i] = CAST_OP(0x55E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x56E0 + i] = CAST_OP(0x56E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x57E0 + i] = CAST_OP(0x57E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x58E0 + i] = CAST_OP(0x58E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x59E0 + i] = CAST_OP(0x59E0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5AE0 + i] = CAST_OP(0x5AE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5BE0 + i] = CAST_OP(0x5BE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5CE0 + i] = CAST_OP(0x5CE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5DE0 + i] = CAST_OP(0x5DE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5EE0 + i] = CAST_OP(0x5EE0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x5FE0 + i] = CAST_OP(0x5FE0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x50E8 + i] = CAST_OP(0x50E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x51E8 + i] = CAST_OP(0x51E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x52E8 + i] = CAST_OP(0x52E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x53E8 + i] = CAST_OP(0x53E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x54E8 + i] = CAST_OP(0x54E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x55E8 + i] = CAST_OP(0x55E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x56E8 + i] = CAST_OP(0x56E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x57E8 + i] = CAST_OP(0x57E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x58E8 + i] = CAST_OP(0x58E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x59E8 + i] = CAST_OP(0x59E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5AE8 + i] = CAST_OP(0x5AE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5BE8 + i] = CAST_OP(0x5BE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5CE8 + i] = CAST_OP(0x5CE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5DE8 + i] = CAST_OP(0x5DE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5EE8 + i] = CAST_OP(0x5EE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5FE8 + i] = CAST_OP(0x5FE8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x50F0 + i] = CAST_OP(0x50F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x51F0 + i] = CAST_OP(0x51F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x52F0 + i] = CAST_OP(0x52F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x53F0 + i] = CAST_OP(0x53F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x54F0 + i] = CAST_OP(0x54F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x55F0 + i] = CAST_OP(0x55F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x56F0 + i] = CAST_OP(0x56F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x57F0 + i] = CAST_OP(0x57F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x58F0 + i] = CAST_OP(0x58F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x59F0 + i] = CAST_OP(0x59F0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5AF0 + i] = CAST_OP(0x5AF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5BF0 + i] = CAST_OP(0x5BF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5CF0 + i] = CAST_OP(0x5CF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5DF0 + i] = CAST_OP(0x5DF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5EF0 + i] = CAST_OP(0x5EF0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5FF0 + i] = CAST_OP(0x5FF0); + JumpTable[0x50F8] = CAST_OP(0x50F8); + JumpTable[0x51F8] = CAST_OP(0x51F8); + JumpTable[0x52F8] = CAST_OP(0x52F8); + JumpTable[0x53F8] = CAST_OP(0x53F8); + JumpTable[0x54F8] = CAST_OP(0x54F8); + JumpTable[0x55F8] = CAST_OP(0x55F8); + JumpTable[0x56F8] = CAST_OP(0x56F8); + JumpTable[0x57F8] = CAST_OP(0x57F8); + JumpTable[0x58F8] = CAST_OP(0x58F8); + JumpTable[0x59F8] = CAST_OP(0x59F8); + JumpTable[0x5AF8] = CAST_OP(0x5AF8); + JumpTable[0x5BF8] = CAST_OP(0x5BF8); + JumpTable[0x5CF8] = CAST_OP(0x5CF8); + JumpTable[0x5DF8] = CAST_OP(0x5DF8); + JumpTable[0x5EF8] = CAST_OP(0x5EF8); + JumpTable[0x5FF8] = CAST_OP(0x5FF8); + JumpTable[0x50F9] = CAST_OP(0x50F9); + JumpTable[0x51F9] = CAST_OP(0x51F9); + JumpTable[0x52F9] = CAST_OP(0x52F9); + JumpTable[0x53F9] = CAST_OP(0x53F9); + JumpTable[0x54F9] = CAST_OP(0x54F9); + JumpTable[0x55F9] = CAST_OP(0x55F9); + JumpTable[0x56F9] = CAST_OP(0x56F9); + JumpTable[0x57F9] = CAST_OP(0x57F9); + JumpTable[0x58F9] = CAST_OP(0x58F9); + JumpTable[0x59F9] = CAST_OP(0x59F9); + JumpTable[0x5AF9] = CAST_OP(0x5AF9); + JumpTable[0x5BF9] = CAST_OP(0x5BF9); + JumpTable[0x5CF9] = CAST_OP(0x5CF9); + JumpTable[0x5DF9] = CAST_OP(0x5DF9); + JumpTable[0x5EF9] = CAST_OP(0x5EF9); + JumpTable[0x5FF9] = CAST_OP(0x5FF9); + JumpTable[0x50DF] = CAST_OP(0x50DF); + JumpTable[0x51DF] = CAST_OP(0x51DF); + JumpTable[0x52DF] = CAST_OP(0x52DF); + JumpTable[0x53DF] = CAST_OP(0x53DF); + JumpTable[0x54DF] = CAST_OP(0x54DF); + JumpTable[0x55DF] = CAST_OP(0x55DF); + JumpTable[0x56DF] = CAST_OP(0x56DF); + JumpTable[0x57DF] = CAST_OP(0x57DF); + JumpTable[0x58DF] = CAST_OP(0x58DF); + JumpTable[0x59DF] = CAST_OP(0x59DF); + JumpTable[0x5ADF] = CAST_OP(0x5ADF); + JumpTable[0x5BDF] = CAST_OP(0x5BDF); + JumpTable[0x5CDF] = CAST_OP(0x5CDF); + JumpTable[0x5DDF] = CAST_OP(0x5DDF); + JumpTable[0x5EDF] = CAST_OP(0x5EDF); + JumpTable[0x5FDF] = CAST_OP(0x5FDF); + JumpTable[0x50E7] = CAST_OP(0x50E7); + JumpTable[0x51E7] = CAST_OP(0x51E7); + JumpTable[0x52E7] = CAST_OP(0x52E7); + JumpTable[0x53E7] = CAST_OP(0x53E7); + JumpTable[0x54E7] = CAST_OP(0x54E7); + JumpTable[0x55E7] = CAST_OP(0x55E7); + JumpTable[0x56E7] = CAST_OP(0x56E7); + JumpTable[0x57E7] = CAST_OP(0x57E7); + JumpTable[0x58E7] = CAST_OP(0x58E7); + JumpTable[0x59E7] = CAST_OP(0x59E7); + JumpTable[0x5AE7] = CAST_OP(0x5AE7); + JumpTable[0x5BE7] = CAST_OP(0x5BE7); + JumpTable[0x5CE7] = CAST_OP(0x5CE7); + JumpTable[0x5DE7] = CAST_OP(0x5DE7); + JumpTable[0x5EE7] = CAST_OP(0x5EE7); + JumpTable[0x5FE7] = CAST_OP(0x5FE7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x50C8 + i] = CAST_OP(0x50C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x51C8 + i] = CAST_OP(0x51C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x52C8 + i] = CAST_OP(0x52C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x53C8 + i] = CAST_OP(0x53C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x54C8 + i] = CAST_OP(0x54C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x55C8 + i] = CAST_OP(0x55C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x56C8 + i] = CAST_OP(0x56C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x57C8 + i] = CAST_OP(0x57C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x58C8 + i] = CAST_OP(0x58C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x59C8 + i] = CAST_OP(0x59C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5AC8 + i] = CAST_OP(0x5AC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5BC8 + i] = CAST_OP(0x5BC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5CC8 + i] = CAST_OP(0x5CC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5DC8 + i] = CAST_OP(0x5DC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5EC8 + i] = CAST_OP(0x5EC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0x5FC8 + i] = CAST_OP(0x5FC8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5000 + i + j] = CAST_OP(0x5000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5010 + i + j] = CAST_OP(0x5010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5018 + i + j] = CAST_OP(0x5018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5020 + i + j] = CAST_OP(0x5020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5028 + i + j] = CAST_OP(0x5028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5030 + i + j] = CAST_OP(0x5030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5038 + i] = CAST_OP(0x5038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5039 + i] = CAST_OP(0x5039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x501F + i] = CAST_OP(0x501F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5027 + i] = CAST_OP(0x5027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5040 + i + j] = CAST_OP(0x5040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5048 + i + j] = CAST_OP(0x5048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5050 + i + j] = CAST_OP(0x5050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5058 + i + j] = CAST_OP(0x5058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5060 + i + j] = CAST_OP(0x5060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5068 + i + j] = CAST_OP(0x5068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5070 + i + j] = CAST_OP(0x5070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5078 + i] = CAST_OP(0x5078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5079 + i] = CAST_OP(0x5079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x505F + i] = CAST_OP(0x505F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5067 + i] = CAST_OP(0x5067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5080 + i + j] = CAST_OP(0x5080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5088 + i + j] = CAST_OP(0x5088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5090 + i + j] = CAST_OP(0x5090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5098 + i + j] = CAST_OP(0x5098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x50A0 + i + j] = CAST_OP(0x50A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x50A8 + i + j] = CAST_OP(0x50A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x50B0 + i + j] = CAST_OP(0x50B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x50B8 + i] = CAST_OP(0x50B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x50B9 + i] = CAST_OP(0x50B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x509F + i] = CAST_OP(0x509F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x50A7 + i] = CAST_OP(0x50A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5100 + i + j] = CAST_OP(0x5100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5110 + i + j] = CAST_OP(0x5110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5118 + i + j] = CAST_OP(0x5118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5120 + i + j] = CAST_OP(0x5120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5128 + i + j] = CAST_OP(0x5128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5130 + i + j] = CAST_OP(0x5130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5138 + i] = CAST_OP(0x5138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5139 + i] = CAST_OP(0x5139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x511F + i] = CAST_OP(0x511F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5127 + i] = CAST_OP(0x5127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5140 + i + j] = CAST_OP(0x5140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5148 + i + j] = CAST_OP(0x5148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5150 + i + j] = CAST_OP(0x5150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5158 + i + j] = CAST_OP(0x5158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5160 + i + j] = CAST_OP(0x5160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5168 + i + j] = CAST_OP(0x5168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5170 + i + j] = CAST_OP(0x5170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5178 + i] = CAST_OP(0x5178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5179 + i] = CAST_OP(0x5179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x515F + i] = CAST_OP(0x515F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x5167 + i] = CAST_OP(0x5167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5180 + i + j] = CAST_OP(0x5180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5188 + i + j] = CAST_OP(0x5188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5190 + i + j] = CAST_OP(0x5190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x5198 + i + j] = CAST_OP(0x5198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x51A0 + i + j] = CAST_OP(0x51A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x51A8 + i + j] = CAST_OP(0x51A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x51B0 + i + j] = CAST_OP(0x51B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x51B8 + i] = CAST_OP(0x51B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x51B9 + i] = CAST_OP(0x51B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x519F + i] = CAST_OP(0x519F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x51A7 + i] = CAST_OP(0x51A7); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6200 + i] = CAST_OP(0x6201); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6300 + i] = CAST_OP(0x6301); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6400 + i] = CAST_OP(0x6401); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6500 + i] = CAST_OP(0x6501); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6600 + i] = CAST_OP(0x6601); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6700 + i] = CAST_OP(0x6701); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6800 + i] = CAST_OP(0x6801); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6900 + i] = CAST_OP(0x6901); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6A00 + i] = CAST_OP(0x6A01); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6B00 + i] = CAST_OP(0x6B01); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6C00 + i] = CAST_OP(0x6C01); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6D00 + i] = CAST_OP(0x6D01); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6E00 + i] = CAST_OP(0x6E01); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6F00 + i] = CAST_OP(0x6F01); + JumpTable[0x6200] = CAST_OP(0x6200); + JumpTable[0x6300] = CAST_OP(0x6300); + JumpTable[0x6400] = CAST_OP(0x6400); + JumpTable[0x6500] = CAST_OP(0x6500); + JumpTable[0x6600] = CAST_OP(0x6600); + JumpTable[0x6700] = CAST_OP(0x6700); + JumpTable[0x6800] = CAST_OP(0x6800); + JumpTable[0x6900] = CAST_OP(0x6900); + JumpTable[0x6A00] = CAST_OP(0x6A00); + JumpTable[0x6B00] = CAST_OP(0x6B00); + JumpTable[0x6C00] = CAST_OP(0x6C00); + JumpTable[0x6D00] = CAST_OP(0x6D00); + JumpTable[0x6E00] = CAST_OP(0x6E00); + JumpTable[0x6F00] = CAST_OP(0x6F00); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6000 + i] = CAST_OP(0x6001); + JumpTable[0x6000] = CAST_OP(0x6000); + for(i = 0x0001; i <= 0x00FF; i += 0x0001) + JumpTable[0x6100 + i] = CAST_OP(0x6101); + JumpTable[0x6100] = CAST_OP(0x6100); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + for(j = 0x0000; j <= 0x00FF; j += 0x0001) + JumpTable[0x7000 + i + j] = CAST_OP(0x7000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8000 + i + j] = CAST_OP(0x8000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8010 + i + j] = CAST_OP(0x8010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8018 + i + j] = CAST_OP(0x8018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8020 + i + j] = CAST_OP(0x8020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8028 + i + j] = CAST_OP(0x8028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8030 + i + j] = CAST_OP(0x8030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8038 + i] = CAST_OP(0x8038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8039 + i] = CAST_OP(0x8039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x803A + i] = CAST_OP(0x803A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x803B + i] = CAST_OP(0x803B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x803C + i] = CAST_OP(0x803C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x801F + i] = CAST_OP(0x801F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8027 + i] = CAST_OP(0x8027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8040 + i + j] = CAST_OP(0x8040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8050 + i + j] = CAST_OP(0x8050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8058 + i + j] = CAST_OP(0x8058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8060 + i + j] = CAST_OP(0x8060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8068 + i + j] = CAST_OP(0x8068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8070 + i + j] = CAST_OP(0x8070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8078 + i] = CAST_OP(0x8078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8079 + i] = CAST_OP(0x8079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x807A + i] = CAST_OP(0x807A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x807B + i] = CAST_OP(0x807B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x807C + i] = CAST_OP(0x807C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x805F + i] = CAST_OP(0x805F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8067 + i] = CAST_OP(0x8067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8080 + i + j] = CAST_OP(0x8080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8090 + i + j] = CAST_OP(0x8090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8098 + i + j] = CAST_OP(0x8098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80A0 + i + j] = CAST_OP(0x80A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80A8 + i + j] = CAST_OP(0x80A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80B0 + i + j] = CAST_OP(0x80B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80B8 + i] = CAST_OP(0x80B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80B9 + i] = CAST_OP(0x80B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80BA + i] = CAST_OP(0x80BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80BB + i] = CAST_OP(0x80BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80BC + i] = CAST_OP(0x80BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x809F + i] = CAST_OP(0x809F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80A7 + i] = CAST_OP(0x80A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8110 + i + j] = CAST_OP(0x8110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8118 + i + j] = CAST_OP(0x8118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8120 + i + j] = CAST_OP(0x8120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8128 + i + j] = CAST_OP(0x8128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8130 + i + j] = CAST_OP(0x8130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8138 + i] = CAST_OP(0x8138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8139 + i] = CAST_OP(0x8139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x811F + i] = CAST_OP(0x811F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8127 + i] = CAST_OP(0x8127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8150 + i + j] = CAST_OP(0x8150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8158 + i + j] = CAST_OP(0x8158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8160 + i + j] = CAST_OP(0x8160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8168 + i + j] = CAST_OP(0x8168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8170 + i + j] = CAST_OP(0x8170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8178 + i] = CAST_OP(0x8178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8179 + i] = CAST_OP(0x8179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x815F + i] = CAST_OP(0x815F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x8167 + i] = CAST_OP(0x8167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8190 + i + j] = CAST_OP(0x8190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8198 + i + j] = CAST_OP(0x8198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81A0 + i + j] = CAST_OP(0x81A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81A8 + i + j] = CAST_OP(0x81A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81B0 + i + j] = CAST_OP(0x81B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81B8 + i] = CAST_OP(0x81B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81B9 + i] = CAST_OP(0x81B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x819F + i] = CAST_OP(0x819F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81A7 + i] = CAST_OP(0x81A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x8100 + i + j] = CAST_OP(0x8100); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x8108 + i + j] = CAST_OP(0x8108); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x810F + i] = CAST_OP(0x810F); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x8F08 + i] = CAST_OP(0x8F08); + JumpTable[0x8F0F] = CAST_OP(0x8F0F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80C0 + i + j] = CAST_OP(0x80C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80D0 + i + j] = CAST_OP(0x80D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80D8 + i + j] = CAST_OP(0x80D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80E0 + i + j] = CAST_OP(0x80E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80E8 + i + j] = CAST_OP(0x80E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x80F0 + i + j] = CAST_OP(0x80F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80F8 + i] = CAST_OP(0x80F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80F9 + i] = CAST_OP(0x80F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80FA + i] = CAST_OP(0x80FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80FB + i] = CAST_OP(0x80FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80FC + i] = CAST_OP(0x80FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80DF + i] = CAST_OP(0x80DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x80E7 + i] = CAST_OP(0x80E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81C0 + i + j] = CAST_OP(0x81C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81D0 + i + j] = CAST_OP(0x81D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81D8 + i + j] = CAST_OP(0x81D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81E0 + i + j] = CAST_OP(0x81E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81E8 + i + j] = CAST_OP(0x81E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x81F0 + i + j] = CAST_OP(0x81F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81F8 + i] = CAST_OP(0x81F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81F9 + i] = CAST_OP(0x81F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81FA + i] = CAST_OP(0x81FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81FB + i] = CAST_OP(0x81FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81FC + i] = CAST_OP(0x81FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81DF + i] = CAST_OP(0x81DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x81E7 + i] = CAST_OP(0x81E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9000 + i + j] = CAST_OP(0x9000); +#if 0 + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9008 + i + j] = CAST_OP(0x9008); +#endif + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9010 + i + j] = CAST_OP(0x9010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9018 + i + j] = CAST_OP(0x9018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9020 + i + j] = CAST_OP(0x9020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9028 + i + j] = CAST_OP(0x9028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9030 + i + j] = CAST_OP(0x9030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9038 + i] = CAST_OP(0x9038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9039 + i] = CAST_OP(0x9039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x903A + i] = CAST_OP(0x903A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x903B + i] = CAST_OP(0x903B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x903C + i] = CAST_OP(0x903C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x901F + i] = CAST_OP(0x901F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9027 + i] = CAST_OP(0x9027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9040 + i + j] = CAST_OP(0x9040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9048 + i + j] = CAST_OP(0x9048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9050 + i + j] = CAST_OP(0x9050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9058 + i + j] = CAST_OP(0x9058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9060 + i + j] = CAST_OP(0x9060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9068 + i + j] = CAST_OP(0x9068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9070 + i + j] = CAST_OP(0x9070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9078 + i] = CAST_OP(0x9078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9079 + i] = CAST_OP(0x9079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x907A + i] = CAST_OP(0x907A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x907B + i] = CAST_OP(0x907B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x907C + i] = CAST_OP(0x907C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x905F + i] = CAST_OP(0x905F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9067 + i] = CAST_OP(0x9067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9080 + i + j] = CAST_OP(0x9080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9088 + i + j] = CAST_OP(0x9088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9090 + i + j] = CAST_OP(0x9090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9098 + i + j] = CAST_OP(0x9098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90A0 + i + j] = CAST_OP(0x90A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90A8 + i + j] = CAST_OP(0x90A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90B0 + i + j] = CAST_OP(0x90B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90B8 + i] = CAST_OP(0x90B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90B9 + i] = CAST_OP(0x90B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90BA + i] = CAST_OP(0x90BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90BB + i] = CAST_OP(0x90BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90BC + i] = CAST_OP(0x90BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x909F + i] = CAST_OP(0x909F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90A7 + i] = CAST_OP(0x90A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9110 + i + j] = CAST_OP(0x9110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9118 + i + j] = CAST_OP(0x9118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9120 + i + j] = CAST_OP(0x9120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9128 + i + j] = CAST_OP(0x9128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9130 + i + j] = CAST_OP(0x9130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9138 + i] = CAST_OP(0x9138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9139 + i] = CAST_OP(0x9139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x911F + i] = CAST_OP(0x911F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9127 + i] = CAST_OP(0x9127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9150 + i + j] = CAST_OP(0x9150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9158 + i + j] = CAST_OP(0x9158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9160 + i + j] = CAST_OP(0x9160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9168 + i + j] = CAST_OP(0x9168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9170 + i + j] = CAST_OP(0x9170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9178 + i] = CAST_OP(0x9178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9179 + i] = CAST_OP(0x9179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x915F + i] = CAST_OP(0x915F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x9167 + i] = CAST_OP(0x9167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9190 + i + j] = CAST_OP(0x9190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9198 + i + j] = CAST_OP(0x9198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91A0 + i + j] = CAST_OP(0x91A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91A8 + i + j] = CAST_OP(0x91A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91B0 + i + j] = CAST_OP(0x91B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91B8 + i] = CAST_OP(0x91B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91B9 + i] = CAST_OP(0x91B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x919F + i] = CAST_OP(0x919F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91A7 + i] = CAST_OP(0x91A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9100 + i + j] = CAST_OP(0x9100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9140 + i + j] = CAST_OP(0x9140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x9180 + i + j] = CAST_OP(0x9180); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x9108 + i + j] = CAST_OP(0x9108); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x9148 + i + j] = CAST_OP(0x9148); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0x9188 + i + j] = CAST_OP(0x9188); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x910F + i] = CAST_OP(0x910F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x914F + i] = CAST_OP(0x914F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0x918F + i] = CAST_OP(0x918F); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x9F08 + i] = CAST_OP(0x9F08); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x9F48 + i] = CAST_OP(0x9F48); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0x9F88 + i] = CAST_OP(0x9F88); + JumpTable[0x9F0F] = CAST_OP(0x9F0F); + JumpTable[0x9F4F] = CAST_OP(0x9F4F); + JumpTable[0x9F8F] = CAST_OP(0x9F8F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90C0 + i + j] = CAST_OP(0x90C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90C8 + i + j] = CAST_OP(0x90C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90D0 + i + j] = CAST_OP(0x90D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90D8 + i + j] = CAST_OP(0x90D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90E0 + i + j] = CAST_OP(0x90E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90E8 + i + j] = CAST_OP(0x90E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x90F0 + i + j] = CAST_OP(0x90F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90F8 + i] = CAST_OP(0x90F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90F9 + i] = CAST_OP(0x90F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90FA + i] = CAST_OP(0x90FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90FB + i] = CAST_OP(0x90FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90FC + i] = CAST_OP(0x90FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90DF + i] = CAST_OP(0x90DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x90E7 + i] = CAST_OP(0x90E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91C0 + i + j] = CAST_OP(0x91C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91C8 + i + j] = CAST_OP(0x91C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91D0 + i + j] = CAST_OP(0x91D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91D8 + i + j] = CAST_OP(0x91D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91E0 + i + j] = CAST_OP(0x91E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91E8 + i + j] = CAST_OP(0x91E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0x91F0 + i + j] = CAST_OP(0x91F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91F8 + i] = CAST_OP(0x91F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91F9 + i] = CAST_OP(0x91F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91FA + i] = CAST_OP(0x91FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91FB + i] = CAST_OP(0x91FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91FC + i] = CAST_OP(0x91FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91DF + i] = CAST_OP(0x91DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0x91E7 + i] = CAST_OP(0x91E7); + for(i = 0x0000; i <= 0x0FFF; i += 0x0001) + JumpTable[0xA000 + i] = CAST_OP(0xA000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB000 + i + j] = CAST_OP(0xB000); +#if 0 + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB008 + i + j] = CAST_OP(0xB008); +#endif + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB010 + i + j] = CAST_OP(0xB010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB018 + i + j] = CAST_OP(0xB018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB020 + i + j] = CAST_OP(0xB020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB028 + i + j] = CAST_OP(0xB028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB030 + i + j] = CAST_OP(0xB030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB038 + i] = CAST_OP(0xB038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB039 + i] = CAST_OP(0xB039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB03A + i] = CAST_OP(0xB03A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB03B + i] = CAST_OP(0xB03B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB03C + i] = CAST_OP(0xB03C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB01F + i] = CAST_OP(0xB01F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB027 + i] = CAST_OP(0xB027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB040 + i + j] = CAST_OP(0xB040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB048 + i + j] = CAST_OP(0xB048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB050 + i + j] = CAST_OP(0xB050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB058 + i + j] = CAST_OP(0xB058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB060 + i + j] = CAST_OP(0xB060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB068 + i + j] = CAST_OP(0xB068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB070 + i + j] = CAST_OP(0xB070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB078 + i] = CAST_OP(0xB078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB079 + i] = CAST_OP(0xB079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB07A + i] = CAST_OP(0xB07A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB07B + i] = CAST_OP(0xB07B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB07C + i] = CAST_OP(0xB07C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB05F + i] = CAST_OP(0xB05F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB067 + i] = CAST_OP(0xB067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB080 + i + j] = CAST_OP(0xB080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB088 + i + j] = CAST_OP(0xB088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB090 + i + j] = CAST_OP(0xB090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB098 + i + j] = CAST_OP(0xB098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0A0 + i + j] = CAST_OP(0xB0A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0A8 + i + j] = CAST_OP(0xB0A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0B0 + i + j] = CAST_OP(0xB0B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0B8 + i] = CAST_OP(0xB0B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0B9 + i] = CAST_OP(0xB0B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0BA + i] = CAST_OP(0xB0BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0BB + i] = CAST_OP(0xB0BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0BC + i] = CAST_OP(0xB0BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB09F + i] = CAST_OP(0xB09F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0A7 + i] = CAST_OP(0xB0A7); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xB108 + i + j] = CAST_OP(0xB108); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xB148 + i + j] = CAST_OP(0xB148); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xB188 + i + j] = CAST_OP(0xB188); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xB10F + i] = CAST_OP(0xB10F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xB14F + i] = CAST_OP(0xB14F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xB18F + i] = CAST_OP(0xB18F); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xBF08 + i] = CAST_OP(0xBF08); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xBF48 + i] = CAST_OP(0xBF48); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xBF88 + i] = CAST_OP(0xBF88); + JumpTable[0xBF0F] = CAST_OP(0xBF0F); + JumpTable[0xBF4F] = CAST_OP(0xBF4F); + JumpTable[0xBF8F] = CAST_OP(0xBF8F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB100 + i + j] = CAST_OP(0xB100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB110 + i + j] = CAST_OP(0xB110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB118 + i + j] = CAST_OP(0xB118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB120 + i + j] = CAST_OP(0xB120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB128 + i + j] = CAST_OP(0xB128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB130 + i + j] = CAST_OP(0xB130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB138 + i] = CAST_OP(0xB138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB139 + i] = CAST_OP(0xB139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB11F + i] = CAST_OP(0xB11F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB127 + i] = CAST_OP(0xB127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB140 + i + j] = CAST_OP(0xB140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB150 + i + j] = CAST_OP(0xB150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB158 + i + j] = CAST_OP(0xB158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB160 + i + j] = CAST_OP(0xB160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB168 + i + j] = CAST_OP(0xB168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB170 + i + j] = CAST_OP(0xB170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB178 + i] = CAST_OP(0xB178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB179 + i] = CAST_OP(0xB179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB15F + i] = CAST_OP(0xB15F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB167 + i] = CAST_OP(0xB167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB180 + i + j] = CAST_OP(0xB180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB190 + i + j] = CAST_OP(0xB190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB198 + i + j] = CAST_OP(0xB198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1A0 + i + j] = CAST_OP(0xB1A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1A8 + i + j] = CAST_OP(0xB1A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1B0 + i + j] = CAST_OP(0xB1B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1B8 + i] = CAST_OP(0xB1B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1B9 + i] = CAST_OP(0xB1B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB19F + i] = CAST_OP(0xB19F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1A7 + i] = CAST_OP(0xB1A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0C0 + i + j] = CAST_OP(0xB0C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0C8 + i + j] = CAST_OP(0xB0C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0D0 + i + j] = CAST_OP(0xB0D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0D8 + i + j] = CAST_OP(0xB0D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0E0 + i + j] = CAST_OP(0xB0E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0E8 + i + j] = CAST_OP(0xB0E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB0F0 + i + j] = CAST_OP(0xB0F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0F8 + i] = CAST_OP(0xB0F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0F9 + i] = CAST_OP(0xB0F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0FA + i] = CAST_OP(0xB0FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0FB + i] = CAST_OP(0xB0FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0FC + i] = CAST_OP(0xB0FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0DF + i] = CAST_OP(0xB0DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB0E7 + i] = CAST_OP(0xB0E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1C0 + i + j] = CAST_OP(0xB1C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1C8 + i + j] = CAST_OP(0xB1C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1D0 + i + j] = CAST_OP(0xB1D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1D8 + i + j] = CAST_OP(0xB1D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1E0 + i + j] = CAST_OP(0xB1E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1E8 + i + j] = CAST_OP(0xB1E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xB1F0 + i + j] = CAST_OP(0xB1F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1F8 + i] = CAST_OP(0xB1F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1F9 + i] = CAST_OP(0xB1F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1FA + i] = CAST_OP(0xB1FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1FB + i] = CAST_OP(0xB1FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1FC + i] = CAST_OP(0xB1FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1DF + i] = CAST_OP(0xB1DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xB1E7 + i] = CAST_OP(0xB1E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC000 + i + j] = CAST_OP(0xC000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC010 + i + j] = CAST_OP(0xC010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC018 + i + j] = CAST_OP(0xC018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC020 + i + j] = CAST_OP(0xC020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC028 + i + j] = CAST_OP(0xC028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC030 + i + j] = CAST_OP(0xC030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC038 + i] = CAST_OP(0xC038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC039 + i] = CAST_OP(0xC039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC03A + i] = CAST_OP(0xC03A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC03B + i] = CAST_OP(0xC03B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC03C + i] = CAST_OP(0xC03C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC01F + i] = CAST_OP(0xC01F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC027 + i] = CAST_OP(0xC027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC040 + i + j] = CAST_OP(0xC040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC050 + i + j] = CAST_OP(0xC050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC058 + i + j] = CAST_OP(0xC058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC060 + i + j] = CAST_OP(0xC060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC068 + i + j] = CAST_OP(0xC068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC070 + i + j] = CAST_OP(0xC070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC078 + i] = CAST_OP(0xC078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC079 + i] = CAST_OP(0xC079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC07A + i] = CAST_OP(0xC07A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC07B + i] = CAST_OP(0xC07B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC07C + i] = CAST_OP(0xC07C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC05F + i] = CAST_OP(0xC05F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC067 + i] = CAST_OP(0xC067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC080 + i + j] = CAST_OP(0xC080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC090 + i + j] = CAST_OP(0xC090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC098 + i + j] = CAST_OP(0xC098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0A0 + i + j] = CAST_OP(0xC0A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0A8 + i + j] = CAST_OP(0xC0A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0B0 + i + j] = CAST_OP(0xC0B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0B8 + i] = CAST_OP(0xC0B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0B9 + i] = CAST_OP(0xC0B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0BA + i] = CAST_OP(0xC0BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0BB + i] = CAST_OP(0xC0BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0BC + i] = CAST_OP(0xC0BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC09F + i] = CAST_OP(0xC09F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0A7 + i] = CAST_OP(0xC0A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC110 + i + j] = CAST_OP(0xC110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC118 + i + j] = CAST_OP(0xC118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC120 + i + j] = CAST_OP(0xC120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC128 + i + j] = CAST_OP(0xC128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC130 + i + j] = CAST_OP(0xC130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC138 + i] = CAST_OP(0xC138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC139 + i] = CAST_OP(0xC139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC11F + i] = CAST_OP(0xC11F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC127 + i] = CAST_OP(0xC127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC150 + i + j] = CAST_OP(0xC150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC158 + i + j] = CAST_OP(0xC158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC160 + i + j] = CAST_OP(0xC160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC168 + i + j] = CAST_OP(0xC168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC170 + i + j] = CAST_OP(0xC170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC178 + i] = CAST_OP(0xC178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC179 + i] = CAST_OP(0xC179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC15F + i] = CAST_OP(0xC15F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC167 + i] = CAST_OP(0xC167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC190 + i + j] = CAST_OP(0xC190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC198 + i + j] = CAST_OP(0xC198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1A0 + i + j] = CAST_OP(0xC1A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1A8 + i + j] = CAST_OP(0xC1A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1B0 + i + j] = CAST_OP(0xC1B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1B8 + i] = CAST_OP(0xC1B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1B9 + i] = CAST_OP(0xC1B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC19F + i] = CAST_OP(0xC19F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1A7 + i] = CAST_OP(0xC1A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC100 + i + j] = CAST_OP(0xC100); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xC108 + i + j] = CAST_OP(0xC108); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xC10F + i] = CAST_OP(0xC10F); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xCF08 + i] = CAST_OP(0xCF08); + JumpTable[0xCF0F] = CAST_OP(0xCF0F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0C0 + i + j] = CAST_OP(0xC0C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0D0 + i + j] = CAST_OP(0xC0D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0D8 + i + j] = CAST_OP(0xC0D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0E0 + i + j] = CAST_OP(0xC0E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0E8 + i + j] = CAST_OP(0xC0E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC0F0 + i + j] = CAST_OP(0xC0F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0F8 + i] = CAST_OP(0xC0F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0F9 + i] = CAST_OP(0xC0F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0FA + i] = CAST_OP(0xC0FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0FB + i] = CAST_OP(0xC0FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0FC + i] = CAST_OP(0xC0FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0DF + i] = CAST_OP(0xC0DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC0E7 + i] = CAST_OP(0xC0E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1C0 + i + j] = CAST_OP(0xC1C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1D0 + i + j] = CAST_OP(0xC1D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1D8 + i + j] = CAST_OP(0xC1D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1E0 + i + j] = CAST_OP(0xC1E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1E8 + i + j] = CAST_OP(0xC1E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC1F0 + i + j] = CAST_OP(0xC1F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1F8 + i] = CAST_OP(0xC1F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1F9 + i] = CAST_OP(0xC1F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1FA + i] = CAST_OP(0xC1FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1FB + i] = CAST_OP(0xC1FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1FC + i] = CAST_OP(0xC1FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1DF + i] = CAST_OP(0xC1DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xC1E7 + i] = CAST_OP(0xC1E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC140 + i + j] = CAST_OP(0xC140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC148 + i + j] = CAST_OP(0xC148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xC188 + i + j] = CAST_OP(0xC188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD000 + i + j] = CAST_OP(0xD000); +#if 0 + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD008 + i + j] = CAST_OP(0xD008); +#endif + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD010 + i + j] = CAST_OP(0xD010); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD018 + i + j] = CAST_OP(0xD018); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD020 + i + j] = CAST_OP(0xD020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD028 + i + j] = CAST_OP(0xD028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD030 + i + j] = CAST_OP(0xD030); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD038 + i] = CAST_OP(0xD038); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD039 + i] = CAST_OP(0xD039); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD03A + i] = CAST_OP(0xD03A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD03B + i] = CAST_OP(0xD03B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD03C + i] = CAST_OP(0xD03C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD01F + i] = CAST_OP(0xD01F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD027 + i] = CAST_OP(0xD027); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD040 + i + j] = CAST_OP(0xD040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD048 + i + j] = CAST_OP(0xD048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD050 + i + j] = CAST_OP(0xD050); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD058 + i + j] = CAST_OP(0xD058); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD060 + i + j] = CAST_OP(0xD060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD068 + i + j] = CAST_OP(0xD068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD070 + i + j] = CAST_OP(0xD070); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD078 + i] = CAST_OP(0xD078); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD079 + i] = CAST_OP(0xD079); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD07A + i] = CAST_OP(0xD07A); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD07B + i] = CAST_OP(0xD07B); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD07C + i] = CAST_OP(0xD07C); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD05F + i] = CAST_OP(0xD05F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD067 + i] = CAST_OP(0xD067); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD080 + i + j] = CAST_OP(0xD080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD088 + i + j] = CAST_OP(0xD088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD090 + i + j] = CAST_OP(0xD090); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD098 + i + j] = CAST_OP(0xD098); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0A0 + i + j] = CAST_OP(0xD0A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0A8 + i + j] = CAST_OP(0xD0A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0B0 + i + j] = CAST_OP(0xD0B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0B8 + i] = CAST_OP(0xD0B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0B9 + i] = CAST_OP(0xD0B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0BA + i] = CAST_OP(0xD0BA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0BB + i] = CAST_OP(0xD0BB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0BC + i] = CAST_OP(0xD0BC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD09F + i] = CAST_OP(0xD09F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0A7 + i] = CAST_OP(0xD0A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD110 + i + j] = CAST_OP(0xD110); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD118 + i + j] = CAST_OP(0xD118); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD120 + i + j] = CAST_OP(0xD120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD128 + i + j] = CAST_OP(0xD128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD130 + i + j] = CAST_OP(0xD130); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD138 + i] = CAST_OP(0xD138); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD139 + i] = CAST_OP(0xD139); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD11F + i] = CAST_OP(0xD11F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD127 + i] = CAST_OP(0xD127); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD150 + i + j] = CAST_OP(0xD150); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD158 + i + j] = CAST_OP(0xD158); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD160 + i + j] = CAST_OP(0xD160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD168 + i + j] = CAST_OP(0xD168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD170 + i + j] = CAST_OP(0xD170); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD178 + i] = CAST_OP(0xD178); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD179 + i] = CAST_OP(0xD179); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD15F + i] = CAST_OP(0xD15F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD167 + i] = CAST_OP(0xD167); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD190 + i + j] = CAST_OP(0xD190); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD198 + i + j] = CAST_OP(0xD198); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1A0 + i + j] = CAST_OP(0xD1A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1A8 + i + j] = CAST_OP(0xD1A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1B0 + i + j] = CAST_OP(0xD1B0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1B8 + i] = CAST_OP(0xD1B8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1B9 + i] = CAST_OP(0xD1B9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD19F + i] = CAST_OP(0xD19F); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1A7 + i] = CAST_OP(0xD1A7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD100 + i + j] = CAST_OP(0xD100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD140 + i + j] = CAST_OP(0xD140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD180 + i + j] = CAST_OP(0xD180); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xD108 + i + j] = CAST_OP(0xD108); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xD148 + i + j] = CAST_OP(0xD148); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0C00; j += 0x0200) + JumpTable[0xD188 + i + j] = CAST_OP(0xD188); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xD10F + i] = CAST_OP(0xD10F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xD14F + i] = CAST_OP(0xD14F); + for(i = 0x0000; i <= 0x0C00; i += 0x0200) + JumpTable[0xD18F + i] = CAST_OP(0xD18F); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xDF08 + i] = CAST_OP(0xDF08); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xDF48 + i] = CAST_OP(0xDF48); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xDF88 + i] = CAST_OP(0xDF88); + JumpTable[0xDF0F] = CAST_OP(0xDF0F); + JumpTable[0xDF4F] = CAST_OP(0xDF4F); + JumpTable[0xDF8F] = CAST_OP(0xDF8F); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0C0 + i + j] = CAST_OP(0xD0C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0C8 + i + j] = CAST_OP(0xD0C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0D0 + i + j] = CAST_OP(0xD0D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0D8 + i + j] = CAST_OP(0xD0D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0E0 + i + j] = CAST_OP(0xD0E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0E8 + i + j] = CAST_OP(0xD0E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD0F0 + i + j] = CAST_OP(0xD0F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0F8 + i] = CAST_OP(0xD0F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0F9 + i] = CAST_OP(0xD0F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0FA + i] = CAST_OP(0xD0FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0FB + i] = CAST_OP(0xD0FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0FC + i] = CAST_OP(0xD0FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0DF + i] = CAST_OP(0xD0DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD0E7 + i] = CAST_OP(0xD0E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1C0 + i + j] = CAST_OP(0xD1C0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1C8 + i + j] = CAST_OP(0xD1C8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1D0 + i + j] = CAST_OP(0xD1D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1D8 + i + j] = CAST_OP(0xD1D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1E0 + i + j] = CAST_OP(0xD1E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1E8 + i + j] = CAST_OP(0xD1E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xD1F0 + i + j] = CAST_OP(0xD1F0); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1F8 + i] = CAST_OP(0xD1F8); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1F9 + i] = CAST_OP(0xD1F9); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1FA + i] = CAST_OP(0xD1FA); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1FB + i] = CAST_OP(0xD1FB); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1FC + i] = CAST_OP(0xD1FC); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1DF + i] = CAST_OP(0xD1DF); + for(i = 0x0000; i <= 0x0E00; i += 0x0200) + JumpTable[0xD1E7 + i] = CAST_OP(0xD1E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE000 + i + j] = CAST_OP(0xE000); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE040 + i + j] = CAST_OP(0xE040); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE080 + i + j] = CAST_OP(0xE080); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE008 + i + j] = CAST_OP(0xE008); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE048 + i + j] = CAST_OP(0xE048); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE088 + i + j] = CAST_OP(0xE088); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE010 + i + j] = CAST_OP(0xE010); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE050 + i + j] = CAST_OP(0xE050); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE090 + i + j] = CAST_OP(0xE090); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE018 + i + j] = CAST_OP(0xE018); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE058 + i + j] = CAST_OP(0xE058); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE098 + i + j] = CAST_OP(0xE098); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE100 + i + j] = CAST_OP(0xE100); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE140 + i + j] = CAST_OP(0xE140); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE180 + i + j] = CAST_OP(0xE180); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE108 + i + j] = CAST_OP(0xE108); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE148 + i + j] = CAST_OP(0xE148); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE188 + i + j] = CAST_OP(0xE188); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE110 + i + j] = CAST_OP(0xE110); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE150 + i + j] = CAST_OP(0xE150); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE190 + i + j] = CAST_OP(0xE190); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE118 + i + j] = CAST_OP(0xE118); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE158 + i + j] = CAST_OP(0xE158); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE198 + i + j] = CAST_OP(0xE198); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE020 + i + j] = CAST_OP(0xE020); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE060 + i + j] = CAST_OP(0xE060); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE0A0 + i + j] = CAST_OP(0xE0A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE028 + i + j] = CAST_OP(0xE028); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE068 + i + j] = CAST_OP(0xE068); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE0A8 + i + j] = CAST_OP(0xE0A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE030 + i + j] = CAST_OP(0xE030); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE070 + i + j] = CAST_OP(0xE070); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE0B0 + i + j] = CAST_OP(0xE0B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE038 + i + j] = CAST_OP(0xE038); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE078 + i + j] = CAST_OP(0xE078); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE0B8 + i + j] = CAST_OP(0xE0B8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE120 + i + j] = CAST_OP(0xE120); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE160 + i + j] = CAST_OP(0xE160); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE1A0 + i + j] = CAST_OP(0xE1A0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE128 + i + j] = CAST_OP(0xE128); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE168 + i + j] = CAST_OP(0xE168); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE1A8 + i + j] = CAST_OP(0xE1A8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE130 + i + j] = CAST_OP(0xE130); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE170 + i + j] = CAST_OP(0xE170); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE1B0 + i + j] = CAST_OP(0xE1B0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE138 + i + j] = CAST_OP(0xE138); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE178 + i + j] = CAST_OP(0xE178); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + for(j = 0x0000; j <= 0x0E00; j += 0x0200) + JumpTable[0xE1B8 + i + j] = CAST_OP(0xE1B8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE0D0 + i] = CAST_OP(0xE0D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE0D8 + i] = CAST_OP(0xE0D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE0E0 + i] =CAST_OP(0xE0E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE0E8 + i] = CAST_OP(0xE0E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE0F0 + i] = CAST_OP(0xE0F0); + JumpTable[0xE0F8] = CAST_OP(0xE0F8); + JumpTable[0xE0F9] = CAST_OP(0xE0F9); + JumpTable[0xE0DF] = CAST_OP(0xE0DF); + JumpTable[0xE0E7] = CAST_OP(0xE0E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE2D0 + i] = CAST_OP(0xE2D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE2D8 + i] = CAST_OP(0xE2D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE2E0 + i] = CAST_OP(0xE2E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE2E8 + i] = CAST_OP(0xE2E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE2F0 + i] = CAST_OP(0xE2F0); + JumpTable[0xE2F8] = CAST_OP(0xE2F8); + JumpTable[0xE2F9] = CAST_OP(0xE2F9); + JumpTable[0xE2DF] = CAST_OP(0xE2DF); + JumpTable[0xE2E7] = CAST_OP(0xE2E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE4D0 + i] = CAST_OP(0xE4D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE4D8 + i] = CAST_OP(0xE4D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE4E0 + i] = CAST_OP(0xE4E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE4E8 + i] = CAST_OP(0xE4E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE4F0 + i] = CAST_OP(0xE4F0); + JumpTable[0xE4F8] = CAST_OP(0xE4F8); + JumpTable[0xE4F9] = CAST_OP(0xE4F9); + JumpTable[0xE4DF] = CAST_OP(0xE4DF); + JumpTable[0xE4E7] = CAST_OP(0xE4E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE6D0 + i] = CAST_OP(0xE6D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE6D8 + i] = CAST_OP(0xE6D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE6E0 + i] = CAST_OP(0xE6E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE6E8 + i] = CAST_OP(0xE6E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE6F0 + i] = CAST_OP(0xE6F0); + JumpTable[0xE6F8] = CAST_OP(0xE6F8); + JumpTable[0xE6F9] = CAST_OP(0xE6F9); + JumpTable[0xE6DF] = CAST_OP(0xE6DF); + JumpTable[0xE6E7] = CAST_OP(0xE6E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE1D0 + i] = CAST_OP(0xE1D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE1D8 + i] = CAST_OP(0xE1D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE1E0 + i] = CAST_OP(0xE1E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE1E8 + i] = CAST_OP(0xE1E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE1F0 + i] = CAST_OP(0xE1F0); + JumpTable[0xE1F8] = CAST_OP(0xE1F8); + JumpTable[0xE1F9] = CAST_OP(0xE1F9); + JumpTable[0xE1DF] = CAST_OP(0xE1DF); + JumpTable[0xE1E7] = CAST_OP(0xE1E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE3D0 + i] = CAST_OP(0xE3D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE3D8 + i] = CAST_OP(0xE3D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE3E0 + i] = CAST_OP(0xE3E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE3E8 + i] = CAST_OP(0xE3E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE3F0 + i] = CAST_OP(0xE3F0); + JumpTable[0xE3F8] = CAST_OP(0xE3F8); + JumpTable[0xE3F9] = CAST_OP(0xE3F9); + JumpTable[0xE3DF] = CAST_OP(0xE3DF); + JumpTable[0xE3E7] = CAST_OP(0xE3E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE5D0 + i] = CAST_OP(0xE5D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE5D8 + i] = CAST_OP(0xE5D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE5E0 + i] = CAST_OP(0xE5E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE5E8 + i] = CAST_OP(0xE5E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE5F0 + i] = CAST_OP(0xE5F0); + JumpTable[0xE5F8] = CAST_OP(0xE5F8); + JumpTable[0xE5F9] = CAST_OP(0xE5F9); + JumpTable[0xE5DF] = CAST_OP(0xE5DF); + JumpTable[0xE5E7] = CAST_OP(0xE5E7); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE7D0 + i] = CAST_OP(0xE7D0); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE7D8 + i] = CAST_OP(0xE7D8); + for(i = 0x0000; i <= 0x0006; i += 0x0001) + JumpTable[0xE7E0 + i] = CAST_OP(0xE7E0); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE7E8 + i] = CAST_OP(0xE7E8); + for(i = 0x0000; i <= 0x0007; i += 0x0001) + JumpTable[0xE7F0 + i] = CAST_OP(0xE7F0); + JumpTable[0xE7F8] = CAST_OP(0xE7F8); + JumpTable[0xE7F9] = CAST_OP(0xE7F9); + JumpTable[0xE7DF] = CAST_OP(0xE7DF); + JumpTable[0xE7E7] = CAST_OP(0xE7E7); + for(i = 0x0000; i <= 0x0FFF; i += 0x0001) + JumpTable[0xF000 + i] = CAST_OP(0xF000); + + initialised = 1; + return 0; +} + +#ifdef PICODRIVE_HACK + +#define INSTALL_IDLE(fake_op_base,real_op,detector,idle_handler,normal_handler) \ + JumpTable[fake_op_base] = CAST_OP(idle_handler); \ + JumpTable[fake_op_base|0x0200] = CAST_OP(normal_handler); \ + JumpTable[real_op] = CAST_OP(detector) + +#define UNDO_IDLE(fake_op_base,real_op,normal_handler) \ + JumpTable[fake_op_base] = JumpTable[fake_op_base|0x0200] = CAST_OP(0x4AFC); \ + JumpTable[real_op] = CAST_OP(normal_handler) + +idle_install: + // printf("install..\n"); + INSTALL_IDLE(0x71fa, 0x66fa, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f8, 0x66f8, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f6, 0x66f6, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x71f2, 0x66f2, idle_detector_bcc8, 0x6601_idle, 0x6601); + INSTALL_IDLE(0x75fa, 0x67fa, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f8, 0x67f8, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f6, 0x67f6, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x75f2, 0x67f2, idle_detector_bcc8, 0x6701_idle, 0x6701); + INSTALL_IDLE(0x7dfe, 0x60fe, idle_detector_bcc8, 0x6001_idle, 0x6001); + INSTALL_IDLE(0x7dfc, 0x60fc, idle_detector_bcc8, 0x6001_idle, 0x6001); + return 0; + +idle_remove: + // printf("remove..\n"); + UNDO_IDLE(0x71fa, 0x66fa, 0x6601); + UNDO_IDLE(0x71f8, 0x66f8, 0x6601); + UNDO_IDLE(0x71f6, 0x66f6, 0x6601); + UNDO_IDLE(0x71f2, 0x66f2, 0x6601); + UNDO_IDLE(0x75fa, 0x67fa, 0x6701); + UNDO_IDLE(0x75f8, 0x67f8, 0x6701); + UNDO_IDLE(0x75f6, 0x67f6, 0x6701); + UNDO_IDLE(0x75f2, 0x67f2, 0x6701); + UNDO_IDLE(0x7dfe, 0x60fe, 0x6001); + UNDO_IDLE(0x7dfc, 0x60fc, 0x6001); + return 0; + +#endif +} + +void *get_jumptab(void) { return JumpTable; } + diff --git a/waterbox/picodrive/cpu/fame/famec_opcodes.h b/waterbox/picodrive/cpu/fame/famec_opcodes.h new file mode 100644 index 0000000000..c690b45c64 --- /dev/null +++ b/waterbox/picodrive/cpu/fame/famec_opcodes.h @@ -0,0 +1,40093 @@ + +#ifdef PICODRIVE_HACK +#define NOT_POLLING g_m68kcontext->not_polling = 1; +#else +#define NOT_POLLING +#endif + +// ORI +OPCODE(0x0000) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + res = DREGu8((Opcode >> 0) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(8) +} + +// ORI +OPCODE(0x0010) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0018) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0020) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ORI +OPCODE(0x0028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ORI +OPCODE(0x0030) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// ORI +OPCODE(0x0038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ORI +OPCODE(0x0039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// ORI +OPCODE(0x001F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0027) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ORI +OPCODE(0x0040) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 0) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 0) & 7) = res; +RET(8) +} + +// ORI +OPCODE(0x0050) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0058) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0060) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ORI +OPCODE(0x0068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ORI +OPCODE(0x0070) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// ORI +OPCODE(0x0078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ORI +OPCODE(0x0079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// ORI +OPCODE(0x005F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ORI +OPCODE(0x0067) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ORI +OPCODE(0x0080) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + res = DREGu32((Opcode >> 0) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(16) +} + +// ORI +OPCODE(0x0090) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ORI +OPCODE(0x0098) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ORI +OPCODE(0x00A0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ORI +OPCODE(0x00A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ORI +OPCODE(0x00B0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// ORI +OPCODE(0x00B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ORI +OPCODE(0x00B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// ORI +OPCODE(0x009F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ORI +OPCODE(0x00A7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ORICCR +OPCODE(0x003C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + res &= M68K_CCR_MASK; + res |= GET_CCR; + SET_CCR(res) +RET(20) +} + +// ORISR +OPCODE(0x007C) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + u32 res; + FETCH_WORD(res); + res &= M68K_SR_MASK; + res |= GET_SR; + SET_SR(res) + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); +#ifdef USE_CYCLONE_TIMING + RET(0) +#else + RET(4) +#endif + } +RET(20) +} + +// ANDI +OPCODE(0x0200) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + res = DREGu8((Opcode >> 0) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(8) +} + +// ANDI +OPCODE(0x0210) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0218) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0220) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ANDI +OPCODE(0x0228) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ANDI +OPCODE(0x0230) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// ANDI +OPCODE(0x0238) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ANDI +OPCODE(0x0239) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// ANDI +OPCODE(0x021F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0227) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ANDI +OPCODE(0x0240) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 0) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 0) & 7) = res; +RET(8) +} + +// ANDI +OPCODE(0x0250) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0258) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0260) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ANDI +OPCODE(0x0268) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ANDI +OPCODE(0x0270) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// ANDI +OPCODE(0x0278) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ANDI +OPCODE(0x0279) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// ANDI +OPCODE(0x025F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ANDI +OPCODE(0x0267) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ANDI +OPCODE(0x0280) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + res = DREGu32((Opcode >> 0) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(16) +#endif +} + +// ANDI +OPCODE(0x0290) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ANDI +OPCODE(0x0298) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ANDI +OPCODE(0x02A0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ANDI +OPCODE(0x02A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ANDI +OPCODE(0x02B0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// ANDI +OPCODE(0x02B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ANDI +OPCODE(0x02B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// ANDI +OPCODE(0x029F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ANDI +OPCODE(0x02A7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ANDICCR +OPCODE(0x023C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + res &= M68K_CCR_MASK; + res &= GET_CCR; + SET_CCR(res) +RET(20) +} + +// ANDISR +OPCODE(0x027C) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_WORD(res); + res &= M68K_SR_MASK; + res &= GET_SR; + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(20) +} + +// EORI +OPCODE(0x0A00) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + res = DREGu8((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(8) +} + +// EORI +OPCODE(0x0A10) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A18) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A20) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// EORI +OPCODE(0x0A28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// EORI +OPCODE(0x0A30) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// EORI +OPCODE(0x0A38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// EORI +OPCODE(0x0A39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// EORI +OPCODE(0x0A1F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A27) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// EORI +OPCODE(0x0A40) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 0) & 7) = res; +RET(8) +} + +// EORI +OPCODE(0x0A50) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A58) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A60) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// EORI +OPCODE(0x0A68) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// EORI +OPCODE(0x0A70) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// EORI +OPCODE(0x0A78) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// EORI +OPCODE(0x0A79) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// EORI +OPCODE(0x0A5F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// EORI +OPCODE(0x0A67) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// EORI +OPCODE(0x0A80) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + res = DREGu32((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(16) +} + +// EORI +OPCODE(0x0A90) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// EORI +OPCODE(0x0A98) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// EORI +OPCODE(0x0AA0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// EORI +OPCODE(0x0AA8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// EORI +OPCODE(0x0AB0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// EORI +OPCODE(0x0AB8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// EORI +OPCODE(0x0AB9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// EORI +OPCODE(0x0A9F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// EORI +OPCODE(0x0AA7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// EORICCR +OPCODE(0x0A3C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + res &= M68K_CCR_MASK; + res ^= GET_CCR; + SET_CCR(res) +RET(20) +} + +// EORISR +OPCODE(0x0A7C) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_WORD(res); + res &= M68K_SR_MASK; + res ^= GET_SR; + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(0) + } +RET(20) +} + +// SUBI +OPCODE(0x0400) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 0) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(8) +} + +// SUBI +OPCODE(0x0410) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0418) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0420) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBI +OPCODE(0x0428) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// SUBI +OPCODE(0x0430) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// SUBI +OPCODE(0x0438) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// SUBI +OPCODE(0x0439) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// SUBI +OPCODE(0x041F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0427) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBI +OPCODE(0x0440) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 0) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(8) +} + +// SUBI +OPCODE(0x0450) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0458) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0460) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBI +OPCODE(0x0468) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// SUBI +OPCODE(0x0470) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// SUBI +OPCODE(0x0478) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// SUBI +OPCODE(0x0479) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// SUBI +OPCODE(0x045F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBI +OPCODE(0x0467) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBI +OPCODE(0x0480) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 0) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(16) +} + +// SUBI +OPCODE(0x0490) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// SUBI +OPCODE(0x0498) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// SUBI +OPCODE(0x04A0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// SUBI +OPCODE(0x04A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// SUBI +OPCODE(0x04B0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// SUBI +OPCODE(0x04B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// SUBI +OPCODE(0x04B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// SUBI +OPCODE(0x049F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// SUBI +OPCODE(0x04A7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDI +OPCODE(0x0600) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 0) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(8) +} + +// ADDI +OPCODE(0x0610) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0618) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0620) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDI +OPCODE(0x0628) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ADDI +OPCODE(0x0630) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// ADDI +OPCODE(0x0638) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ADDI +OPCODE(0x0639) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// ADDI +OPCODE(0x061F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0627) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDI +OPCODE(0x0640) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 0) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(8) +} + +// ADDI +OPCODE(0x0650) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0658) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0660) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDI +OPCODE(0x0668) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ADDI +OPCODE(0x0670) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// ADDI +OPCODE(0x0678) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ADDI +OPCODE(0x0679) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// ADDI +OPCODE(0x065F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDI +OPCODE(0x0667) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDI +OPCODE(0x0680) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 0) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(16) +} + +// ADDI +OPCODE(0x0690) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ADDI +OPCODE(0x0698) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ADDI +OPCODE(0x06A0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDI +OPCODE(0x06A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ADDI +OPCODE(0x06B0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// ADDI +OPCODE(0x06B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// ADDI +OPCODE(0x06B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// ADDI +OPCODE(0x069F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ADDI +OPCODE(0x06A7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// CMPI +OPCODE(0x0C00) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 0) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; +RET(8) +} + +// CMPI +OPCODE(0x0C10) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C18) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C20) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(14) +} + +// CMPI +OPCODE(0x0C28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(16) +} + +// CMPI +OPCODE(0x0C30) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(18) +} + +// CMPI +OPCODE(0x0C38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(16) +} + +// CMPI +OPCODE(0x0C39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(20) +} + +// CMPI +OPCODE(0x0C1F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C27) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(14) +} + +// CMPI +OPCODE(0x0C40) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 0) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; +RET(8) +} + +// CMPI +OPCODE(0x0C50) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C58) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C60) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(14) +} + +// CMPI +OPCODE(0x0C68) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(16) +} + +// CMPI +OPCODE(0x0C70) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(18) +} + +// CMPI +OPCODE(0x0C78) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(16) +} + +// CMPI +OPCODE(0x0C79) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(20) +} + +// CMPI +OPCODE(0x0C5F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMPI +OPCODE(0x0C67) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(14) +} + +// CMPI +OPCODE(0x0C80) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 0) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(14) +} + +// CMPI +OPCODE(0x0C90) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPI +OPCODE(0x0C98) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPI +OPCODE(0x0CA0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(22) +} + +// CMPI +OPCODE(0x0CA8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(24) +} + +// CMPI +OPCODE(0x0CB0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(26) +} + +// CMPI +OPCODE(0x0CB8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(24) +} + +// CMPI +OPCODE(0x0CB9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(28) +} + +// CMPI +OPCODE(0x0C9F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPI +OPCODE(0x0CA7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(22) +} + +// BTSTn +OPCODE(0x0800) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; +RET(10) +} + +// BTSTn +OPCODE(0x0810) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTSTn +OPCODE(0x0818) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTSTn +OPCODE(0x0820) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(14) +} + +// BTSTn +OPCODE(0x0828) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(16) +} + +// BTSTn +OPCODE(0x0830) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(18) +} + +// BTSTn +OPCODE(0x0838) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(16) +} + +// BTSTn +OPCODE(0x0839) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(20) +} + +// BTSTn +OPCODE(0x083A) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(16) +} + +// BTSTn +OPCODE(0x083B) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(18) +} + +// BTSTn +OPCODE(0x081F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTSTn +OPCODE(0x0827) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(14) +} + +// BCHGn +OPCODE(0x0840) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res ^= src; + DREGu32((Opcode >> 0) & 7) = res; +RET(12) +} + +// BCHGn +OPCODE(0x0850) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCHGn +OPCODE(0x0858) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCHGn +OPCODE(0x0860) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BCHGn +OPCODE(0x0868) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCHGn +OPCODE(0x0870) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// BCHGn +OPCODE(0x0878) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCHGn +OPCODE(0x0879) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// BCHGn +OPCODE(0x085F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCHGn +OPCODE(0x0867) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BCLRn +OPCODE(0x0880) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res &= ~src; + DREGu32((Opcode >> 0) & 7) = res; +RET(14) +} + +// BCLRn +OPCODE(0x0890) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCLRn +OPCODE(0x0898) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCLRn +OPCODE(0x08A0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BCLRn +OPCODE(0x08A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCLRn +OPCODE(0x08B0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// BCLRn +OPCODE(0x08B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCLRn +OPCODE(0x08B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// BCLRn +OPCODE(0x089F) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCLRn +OPCODE(0x08A7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BSETn +OPCODE(0x08C0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res |= src; + DREGu32((Opcode >> 0) & 7) = res; +RET(12) +} + +// BSETn +OPCODE(0x08D0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BSETn +OPCODE(0x08D8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BSETn +OPCODE(0x08E0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BSETn +OPCODE(0x08E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BSETn +OPCODE(0x08F0) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// BSETn +OPCODE(0x08F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BSETn +OPCODE(0x08F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// BSETn +OPCODE(0x08DF) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BSETn +OPCODE(0x08E7) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BTST +OPCODE(0x0100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; +RET(6) +} + +// BTST +OPCODE(0x0110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(8) +} + +// BTST +OPCODE(0x0118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(8) +} + +// BTST +OPCODE(0x0120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(10) +} + +// BTST +OPCODE(0x0128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTST +OPCODE(0x0130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(14) +} + +// BTST +OPCODE(0x0138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTST +OPCODE(0x0139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(16) +} + +// BTST +OPCODE(0x013A) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(12) +} + +// BTST +OPCODE(0x013B) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(14) +} + +// BTST +OPCODE(0x013C) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_BYTE(res); + flag_NotZ = res & src; +RET(8) +} + +// BTST +OPCODE(0x011F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(8) +} + +// BTST +OPCODE(0x0127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + POST_IO +RET(10) +} + +// BCHG +OPCODE(0x0140) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res ^= src; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// BCHG +OPCODE(0x0150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCHG +OPCODE(0x0158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCHG +OPCODE(0x0160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// BCHG +OPCODE(0x0168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCHG +OPCODE(0x0170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BCHG +OPCODE(0x0178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCHG +OPCODE(0x0179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCHG +OPCODE(0x015F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCHG +OPCODE(0x0167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res ^= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// BCLR +OPCODE(0x0180) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res &= ~src; + DREGu32((Opcode >> 0) & 7) = res; +RET(10) +} + +// BCLR +OPCODE(0x0190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCLR +OPCODE(0x0198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCLR +OPCODE(0x01A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// BCLR +OPCODE(0x01A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCLR +OPCODE(0x01B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BCLR +OPCODE(0x01B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BCLR +OPCODE(0x01B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BCLR +OPCODE(0x019F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BCLR +OPCODE(0x01A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res &= ~src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// BSET +OPCODE(0x01C0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + src = 1 << (src & 31); + res = DREGu32((Opcode >> 0) & 7); + flag_NotZ = res & src; + res |= src; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// BSET +OPCODE(0x01D0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BSET +OPCODE(0x01D8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BSET +OPCODE(0x01E0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// BSET +OPCODE(0x01E8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BSET +OPCODE(0x01F0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// BSET +OPCODE(0x01F8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// BSET +OPCODE(0x01F9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// BSET +OPCODE(0x01DF) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// BSET +OPCODE(0x01E7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + src = 1 << (src & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_NotZ = res & src; + res |= src; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEPWaD +OPCODE(0x0108) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr + 0, res) + READ_BYTE_F(adr + 2, src) + DREGu16((Opcode >> 9) & 7) = (res << 8) | src; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(24) +#endif +} + +// MOVEPLaD +OPCODE(0x0148) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res <<= 24; + adr += 2; + READ_BYTE_F(adr, src) + res |= src << 16; + adr += 2; + READ_BYTE_F(adr, src) + res |= src << 8; + adr += 2; + READ_BYTE_F(adr, src) + DREG((Opcode >> 9) & 7) = res | src; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(24) +#else +RET(32) +#endif +} + +// MOVEPWDa +OPCODE(0x0188) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + WRITE_BYTE_F(adr + 0, res >> 8) + WRITE_BYTE_F(adr + 2, res >> 0) + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(24) +#endif +} + +// MOVEPLDa +OPCODE(0x01C8) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + WRITE_BYTE_F(adr, res >> 24) + adr += 2; + WRITE_BYTE_F(adr, res >> 16) + adr += 2; + WRITE_BYTE_F(adr, res >> 8) + adr += 2; + WRITE_BYTE_F(adr, res >> 0) + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(24) +#else +RET(32) +#endif +} + +// MOVEB +OPCODE(0x1000) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEB +OPCODE(0x1080) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x10C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x1100) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x1140) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1180) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x11C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x13C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1EC0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x1F00) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(8) +} + +#if 0 +// MOVEB +OPCODE(0x1008) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +*/ +RET(4) +} + +// MOVEB +OPCODE(0x1088) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(8) +} + +// MOVEB +OPCODE(0x10C8) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(8) +} + +// MOVEB +OPCODE(0x1108) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(8) +} + +// MOVEB +OPCODE(0x1148) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(12) +} + +// MOVEB +OPCODE(0x1188) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(14) +} + +// MOVEB +OPCODE(0x11C8) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(12) +} + +// MOVEB +OPCODE(0x13C8) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(16) +} + +// MOVEB +OPCODE(0x1EC8) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(8) +} + +// MOVEB +OPCODE(0x1F08) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +*/ +RET(8) +} +#endif + +// MOVEB +OPCODE(0x1010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x1090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1110) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1150) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1190) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x13D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1ED0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1F10) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x1098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1118) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1158) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1198) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x13D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1ED8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1F18) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// MOVEB +OPCODE(0x10A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x10E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1120) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1160) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x11E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x13E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x1EE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1F20) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x10E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1128) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1168) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x11A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x11E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x13E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x1EE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1F28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x10B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x10F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x1130) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x1170) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x11B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x11F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x13F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(26) +} + +// MOVEB +OPCODE(0x1EF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x1F30) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x1038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x10F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1138) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1178) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x11B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x11F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x13F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x1EF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1F38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x10B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x10F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1139) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1179) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x11B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(26) +} + +// MOVEB +OPCODE(0x11F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x13F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(28) +} + +// MOVEB +OPCODE(0x1EF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1F39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x103A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x10FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x113A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x117A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x11BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x11FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x13FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x1EFA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x1F3A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x103B) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x10BB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x10FB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x113B) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x117B) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x11BB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(24) +} + +// MOVEB +OPCODE(0x11FB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x13FB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(26) +} + +// MOVEB +OPCODE(0x1EFB) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x1F3B) +{ + u32 adr, res; + u32 src, dst; + + adr = (uptr)(PC) - BasePC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x103C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(8) +} + +// MOVEB +OPCODE(0x10BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x113C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x117C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x11BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x13FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1EFC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1F3C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x101F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEB +OPCODE(0x109F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x10DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x111F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x115F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x119F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// MOVEB +OPCODE(0x13DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x1EDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1F1F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// MOVEB +OPCODE(0x1027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// MOVEB +OPCODE(0x10A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x10E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1127) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1167) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x11A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// MOVEB +OPCODE(0x11E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_SWORD(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MOVEB +OPCODE(0x13E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + FETCH_LONG(adr); + WRITE_BYTE_F(adr, res) + POST_IO +RET(22) +} + +// MOVEB +OPCODE(0x1EE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7); + AREG(7) += 2; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEB +OPCODE(0x1F27) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// MOVEL +OPCODE(0x2000) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEL +OPCODE(0x2080) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x20C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2100) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2140) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x2180) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(18) +} + +// MOVEL +OPCODE(0x21C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x23C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2EC0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2F00) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2008) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEL +OPCODE(0x2088) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x20C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2108) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2148) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x2188) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(18) +} + +// MOVEL +OPCODE(0x21C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x23C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2EC8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2F08) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x20D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2110) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2150) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2190) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x23D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2ED0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2F10) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x2098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x20D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2118) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2158) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2198) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x23D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2ED8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2F18) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEL +OPCODE(0x20A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x20E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2120) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2160) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x21E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x23E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x2EE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2F20) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x20A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x20E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2128) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2168) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x21A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x21E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x23E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x2EE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2F28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// MOVEL +OPCODE(0x20B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x20F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x2130) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x2170) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x21B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x21F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x23F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// MOVEL +OPCODE(0x2EF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x2F30) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x2038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x20B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x20F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2138) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2178) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x21B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x21F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x23F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x2EF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2F38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x20B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x20F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2139) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2179) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x21B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// MOVEL +OPCODE(0x21F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x23F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(36) +} + +// MOVEL +OPCODE(0x2EF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2F39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x203A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEL +OPCODE(0x20BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x20FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x213A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x217A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x21BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x21FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x23FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x2EFA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x2F3A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x203B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// MOVEL +OPCODE(0x20BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x20FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x213B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x217B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x21BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(32) +} + +// MOVEL +OPCODE(0x21FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x23FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(34) +} + +// MOVEL +OPCODE(0x2EFB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x2F3B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x203C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(12) +} + +// MOVEL +OPCODE(0x20BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x20FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x213C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x217C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x21BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x23FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2EFC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2F3C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x201F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEL +OPCODE(0x209F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x20DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x211F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x215F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x219F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// MOVEL +OPCODE(0x23DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x2EDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2F1F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(20) +} + +// MOVEL +OPCODE(0x2027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEL +OPCODE(0x20A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x20E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2127) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2167) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x21A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// MOVEL +OPCODE(0x21E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_SWORD(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// MOVEL +OPCODE(0x23E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + FETCH_LONG(adr); + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// MOVEL +OPCODE(0x2EE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7); + AREG(7) += 4; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVEL +OPCODE(0x2F27) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + adr = AREG(7) - 4; + AREG(7) = adr; + WRITE_LONG_DEC_F(adr, res) + POST_IO +RET(22) +} + +// MOVEAL +OPCODE(0x2040) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)DREGs32((Opcode >> 0) & 7); + AREG((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEAL +OPCODE(0x2048) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)AREGs32((Opcode >> 0) & 7); + AREG((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEAL +OPCODE(0x2050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAL +OPCODE(0x2058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAL +OPCODE(0x2060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEAL +OPCODE(0x2068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEAL +OPCODE(0x2070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// MOVEAL +OPCODE(0x2078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEAL +OPCODE(0x2079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// MOVEAL +OPCODE(0x207A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEAL +OPCODE(0x207B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// MOVEAL +OPCODE(0x207C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(res); + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// MOVEAL +OPCODE(0x205F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAL +OPCODE(0x2067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READSX_LONG_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3000) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEW +OPCODE(0x3080) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x30C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3100) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3140) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3180) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x31C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x33C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3EC0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3F00) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3008) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEW +OPCODE(0x3088) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x30C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3108) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3148) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3188) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x31C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x33C8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3EC8) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3F08) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3110) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3150) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3190) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x33D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3ED0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3F10) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x3098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3118) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3158) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3198) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x33D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3ED8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3F18) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// MOVEW +OPCODE(0x30A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x30E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3120) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3160) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x31E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x33E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x3EE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3F20) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x30E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3128) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3168) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x31A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x31E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x33E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x3EE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3F28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x30B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x30F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x3130) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x3170) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x31B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x31F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x33F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(26) +} + +// MOVEW +OPCODE(0x3EF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x3F30) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x3038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x30F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3138) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3178) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x31B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x31F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x33F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x3EF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3F38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x30B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x30F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3139) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3179) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x31B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(26) +} + +// MOVEW +OPCODE(0x31F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x33F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(28) +} + +// MOVEW +OPCODE(0x3EF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3F39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x303A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x30FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x313A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x317A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x31BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x31FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x33FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x3EFA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x3F3A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x303B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x30BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x30FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x313B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x317B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x31BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(24) +} + +// MOVEW +OPCODE(0x31FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x33FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(26) +} + +// MOVEW +OPCODE(0x3EFB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x3F3B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x303C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(8) +} + +// MOVEW +OPCODE(0x30BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x313C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x317C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x31BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x33FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3EFC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3F3C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x301F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEW +OPCODE(0x309F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x30DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x311F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x315F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x319F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVEW +OPCODE(0x33DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x3EDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3F1F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVEW +OPCODE(0x3027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// MOVEW +OPCODE(0x30A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x30E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3127) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3167) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 9) & 7); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x31A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG((Opcode >> 9) & 7); + DECODE_EXT_WORD + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVEW +OPCODE(0x31E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_SWORD(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVEW +OPCODE(0x33E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + FETCH_LONG(adr); + WRITE_WORD_F(adr, res) + POST_IO +RET(22) +} + +// MOVEW +OPCODE(0x3EE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7); + AREG(7) += 2; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEW +OPCODE(0x3F27) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + adr = AREG(7) - 2; + AREG(7) = adr; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEAW +OPCODE(0x3040) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)DREGs16((Opcode >> 0) & 7); + AREG((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEAW +OPCODE(0x3048) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)AREGs16((Opcode >> 0) & 7); + AREG((Opcode >> 9) & 7) = res; +RET(4) +} + +// MOVEAW +OPCODE(0x3050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEAW +OPCODE(0x3058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEAW +OPCODE(0x3060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// MOVEAW +OPCODE(0x3068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAW +OPCODE(0x3070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEAW +OPCODE(0x3078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAW +OPCODE(0x3079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// MOVEAW +OPCODE(0x307A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// MOVEAW +OPCODE(0x307B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// MOVEAW +OPCODE(0x307C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(res); + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// MOVEAW +OPCODE(0x305F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// MOVEAW +OPCODE(0x3067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, res) + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// NEGX +OPCODE(0x4000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// NEGX +OPCODE(0x4010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NEGX +OPCODE(0x4028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NEGX +OPCODE(0x4030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// NEGX +OPCODE(0x4038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NEGX +OPCODE(0x4039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// NEGX +OPCODE(0x401F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NEGX +OPCODE(0x4040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// NEGX +OPCODE(0x4050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NEGX +OPCODE(0x4068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NEGX +OPCODE(0x4070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// NEGX +OPCODE(0x4078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NEGX +OPCODE(0x4079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// NEGX +OPCODE(0x405F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEGX +OPCODE(0x4067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NEGX +OPCODE(0x4080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(6) +} + +// NEGX +OPCODE(0x4090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) | (src >> 1) | (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEGX +OPCODE(0x4098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEGX +OPCODE(0x40A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// NEGX +OPCODE(0x40A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NEGX +OPCODE(0x40B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// NEGX +OPCODE(0x40B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NEGX +OPCODE(0x40B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// NEGX +OPCODE(0x409F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEGX +OPCODE(0x40A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = -src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_V = (res & src) >> 24; +flag_X = flag_C = (res?1:0)<<8; +// flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// CLR +OPCODE(0x4200) +{ + u32 adr, res; + u32 src, dst; + + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// CLR +OPCODE(0x4210) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4218) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4220) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// CLR +OPCODE(0x4228) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// CLR +OPCODE(0x4230) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// CLR +OPCODE(0x4238) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// CLR +OPCODE(0x4239) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// CLR +OPCODE(0x421F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4227) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// CLR +OPCODE(0x4240) +{ + u32 adr, res; + u32 src, dst; + + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// CLR +OPCODE(0x4250) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4258) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4260) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// CLR +OPCODE(0x4268) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// CLR +OPCODE(0x4270) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// CLR +OPCODE(0x4278) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// CLR +OPCODE(0x4279) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// CLR +OPCODE(0x425F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// CLR +OPCODE(0x4267) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// CLR +OPCODE(0x4280) +{ + u32 adr, res; + u32 src, dst; + + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + DREGu32((Opcode >> 0) & 7) = res; +RET(6) +} + +// CLR +OPCODE(0x4290) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// CLR +OPCODE(0x4298) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// CLR +OPCODE(0x42A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// CLR +OPCODE(0x42A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// CLR +OPCODE(0x42B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// CLR +OPCODE(0x42B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// CLR +OPCODE(0x42B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// CLR +OPCODE(0x429F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// CLR +OPCODE(0x42A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + res = 0; + flag_N = flag_NotZ = flag_V = flag_C = 0; + PRE_IO + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// NEG +OPCODE(0x4400) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// NEG +OPCODE(0x4410) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4418) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4420) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NEG +OPCODE(0x4428) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NEG +OPCODE(0x4430) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// NEG +OPCODE(0x4438) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NEG +OPCODE(0x4439) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// NEG +OPCODE(0x441F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4427) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = -src; + flag_V = res & src; + flag_N = flag_X = flag_C = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NEG +OPCODE(0x4440) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// NEG +OPCODE(0x4450) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4458) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4460) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NEG +OPCODE(0x4468) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NEG +OPCODE(0x4470) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// NEG +OPCODE(0x4478) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NEG +OPCODE(0x4479) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// NEG +OPCODE(0x445F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NEG +OPCODE(0x4467) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = -src; + flag_V = (res & src) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NEG +OPCODE(0x4480) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(6) +} + +// NEG +OPCODE(0x4490) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEG +OPCODE(0x4498) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEG +OPCODE(0x44A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// NEG +OPCODE(0x44A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NEG +OPCODE(0x44B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// NEG +OPCODE(0x44B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NEG +OPCODE(0x44B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// NEG +OPCODE(0x449F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NEG +OPCODE(0x44A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = -src; + flag_NotZ = res; + flag_V = (res & src) >> 24; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// NOT +OPCODE(0x4600) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// NOT +OPCODE(0x4610) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4618) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4620) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NOT +OPCODE(0x4628) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NOT +OPCODE(0x4630) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// NOT +OPCODE(0x4638) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// NOT +OPCODE(0x4639) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// NOT +OPCODE(0x461F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4627) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_N = res; + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// NOT +OPCODE(0x4640) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// NOT +OPCODE(0x4650) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4658) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4660) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NOT +OPCODE(0x4668) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NOT +OPCODE(0x4670) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// NOT +OPCODE(0x4678) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// NOT +OPCODE(0x4679) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// NOT +OPCODE(0x465F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// NOT +OPCODE(0x4667) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res & 0xFFFF; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// NOT +OPCODE(0x4680) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(6) +} + +// NOT +OPCODE(0x4690) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NOT +OPCODE(0x4698) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NOT +OPCODE(0x46A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// NOT +OPCODE(0x46A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NOT +OPCODE(0x46B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// NOT +OPCODE(0x46B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// NOT +OPCODE(0x46B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// NOT +OPCODE(0x469F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// NOT +OPCODE(0x46A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = ~src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// MOVESRa +OPCODE(0x40C0) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// MOVESRa +OPCODE(0x40D0) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVESRa +OPCODE(0x40D8) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVESRa +OPCODE(0x40E0) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVESRa +OPCODE(0x40E8) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVESRa +OPCODE(0x40F0) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// MOVESRa +OPCODE(0x40F8) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + FETCH_SWORD(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// MOVESRa +OPCODE(0x40F9) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + FETCH_LONG(adr); + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// MOVESRa +OPCODE(0x40DF) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// MOVESRa +OPCODE(0x40E7) +{ + u32 adr, res; + u32 src, dst; + + res = GET_SR; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// MOVEaCCR +OPCODE(0x44C0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + SET_CCR(res) +RET(12) +} + +// MOVEaCCR +OPCODE(0x44D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(16) +} + +// MOVEaCCR +OPCODE(0x44D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(16) +} + +// MOVEaCCR +OPCODE(0x44E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(18) +} + +// MOVEaCCR +OPCODE(0x44E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(20) +} + +// MOVEaCCR +OPCODE(0x44F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(22) +} + +// MOVEaCCR +OPCODE(0x44F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(20) +} + +// MOVEaCCR +OPCODE(0x44F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(24) +} + +// MOVEaCCR +OPCODE(0x44FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(20) +} + +// MOVEaCCR +OPCODE(0x44FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(22) +} + +// MOVEaCCR +OPCODE(0x44FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(res); + SET_CCR(res) +RET(16) +} + +// MOVEaCCR +OPCODE(0x44DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(16) +} + +// MOVEaCCR +OPCODE(0x44E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + SET_CCR(res) + POST_IO +RET(18) +} + +// MOVEaSR +OPCODE(0x46C0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + res = DREGu16((Opcode >> 0) & 7); + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + CHECK_INT_TO_JUMP(12) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(12) +} + +// MOVEaSR +OPCODE(0x46D0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(16) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(16) +} + +// MOVEaSR +OPCODE(0x46D8) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(16) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(16) +} + +// MOVEaSR +OPCODE(0x46E0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(18) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(18) +} + +// MOVEaSR +OPCODE(0x46E8) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(20) +} + +// MOVEaSR +OPCODE(0x46F0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(22) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(22) +} + + +// MOVEaSR +OPCODE(0x46F8) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(20) +} + +// MOVEaSR +OPCODE(0x46F9) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(24) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(24) +} + +// MOVEaSR +OPCODE(0x46FA) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(20) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(20) +} + +// MOVEaSR +OPCODE(0x46FB) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(22) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(22) +} + +// MOVEaSR +OPCODE(0x46FC) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + FETCH_WORD(res); + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + CHECK_INT_TO_JUMP(16) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(16) +} + +// MOVEaSR +OPCODE(0x46DF) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(16) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(16) +} + +// MOVEaSR +OPCODE(0x46E7) +{ + u32 adr, res; + u32 src, dst; + + if (flag_S) + { + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + CHECK_INT_TO_JUMP(18) + } + else + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } +RET(18) +} + +// NBCD +OPCODE(0x4800) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; +RET(6) +} + +// NBCD +OPCODE(0x4810) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(12) +} + +// NBCD +OPCODE(0x4818) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(12) +} + +// NBCD +OPCODE(0x4820) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(14) +} + +// NBCD +OPCODE(0x4828) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(16) +} + +// NBCD +OPCODE(0x4830) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(18) +} + +// NBCD +OPCODE(0x4838) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(16) +} + +// NBCD +OPCODE(0x4839) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(20) +} + +// NBCD +OPCODE(0x481F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(12) +} + +// NBCD +OPCODE(0x4827) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res = 0x9a - res - ((flag_X >> M68K_SR_X_SFT) & 1); + + if (res != 0x9a) + { + if ((res & 0x0f) == 0xa) res = (res & 0xf0) + 0x10; + res &= 0xFF; + WRITE_BYTE_F(adr, res) + flag_NotZ |= res; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_N = res; + POST_IO +RET(14) +} + +// PEA +OPCODE(0x4850) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(12) +} + +// PEA +OPCODE(0x4868) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(16) +} + +// PEA +OPCODE(0x4870) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(20) +} + +// PEA +OPCODE(0x4878) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(16) +} + +// PEA +OPCODE(0x4879) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(20) +} + +// PEA +OPCODE(0x487A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(16) +} + +// PEA +OPCODE(0x487B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + PUSH_32_F(adr) + POST_IO +RET(20) +} + +// SWAP +OPCODE(0x4840) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + res = (res >> 16) | (res << 16); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(4) +} + +// MOVEMRa +OPCODE(0x4890) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(12) +#endif +} + +// MOVEMRa +OPCODE(0x48A0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &AREGu32(7); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + adr -= 2; + WRITE_WORD_F(adr, *psrc) + } + psrc--; + } while (res >>= 1); + AREG((Opcode >> 0) & 7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (dst - adr) * 2; +RET(8) +} + +// MOVEMRa +OPCODE(0x48A8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(20) +#endif +} + +// MOVEMRa +OPCODE(0x48B0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(24) +#endif +} + +// MOVEMRa +OPCODE(0x48B8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(20) +#endif +} + +// MOVEMRa +OPCODE(0x48B9) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_LONG(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(28) +#endif +} + +// MOVEMRa +OPCODE(0x48A7) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG(7); + psrc = &AREGu32(7); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + adr -= 2; + WRITE_WORD_F(adr, *psrc) + } + psrc--; + } while (res >>= 1); + AREG(7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (dst - adr) * 2; +RET(8) +} + +// MOVEMRa +OPCODE(0x48D0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(16) +#endif +} + +// MOVEMRa +OPCODE(0x48E0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &AREGu32(7); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + adr -= 4; + WRITE_LONG_DEC_F(adr, *psrc) + } + psrc--; + } while (res >>= 1); + AREG((Opcode >> 0) & 7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (dst - adr) * 2; +RET(8) +} + +// MOVEMRa +OPCODE(0x48E8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(24) +#endif +} + +// MOVEMRa +OPCODE(0x48F0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(28) +#endif +} + +// MOVEMRa +OPCODE(0x48F8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(24) +#endif +} + +// MOVEMRa +OPCODE(0x48F9) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_LONG(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + WRITE_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(32) +#endif +} + +// MOVEMRa +OPCODE(0x48E7) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG(7); + psrc = &AREGu32(7); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + adr -= 4; + WRITE_LONG_DEC_F(adr, *psrc) + } + psrc--; + } while (res >>= 1); + AREG(7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (dst - adr) * 2; +RET(8) +} + +// EXT +OPCODE(0x4880) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)DREGs8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// EXT +OPCODE(0x48C0) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)DREGs16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu32((Opcode >> 0) & 7) = res; +RET(4) +} + +// TST +OPCODE(0x4A00) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; +RET(4) +} + +// TST +OPCODE(0x4A10) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A18) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A20) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(10) +} + +// TST +OPCODE(0x4A28) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4A30) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(14) +} + +// TST +OPCODE(0x4A38) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4A39) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(16) +} + +// TST +OPCODE(0x4A1F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A27) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + POST_IO +RET(10) +} + +// TST +OPCODE(0x4A40) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu16((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; +RET(4) +} + +// TST +OPCODE(0x4A50) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A58) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A60) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(10) +} + +// TST +OPCODE(0x4A68) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4A70) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(14) +} + +// TST +OPCODE(0x4A78) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4A79) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(16) +} + +// TST +OPCODE(0x4A5F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(8) +} + +// TST +OPCODE(0x4A67) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + POST_IO +RET(10) +} + +// TST +OPCODE(0x4A80) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; +RET(4) +} + +// TST +OPCODE(0x4A90) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4A98) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4AA0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// TST +OPCODE(0x4AA8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// TST +OPCODE(0x4AB0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// TST +OPCODE(0x4AB8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// TST +OPCODE(0x4AB9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// TST +OPCODE(0x4A9F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(12) +} + +// TST +OPCODE(0x4AA7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// TAS +OPCODE(0x4AC0) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu8((Opcode >> 0) & 7); + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + res |= 0x80; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// TAS +OPCODE(0x4AD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(8) +#endif +} + +// TAS +OPCODE(0x4AD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(8) +#endif +} + +// TAS +OPCODE(0x4AE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(10) +#endif +} + +// TAS +OPCODE(0x4AE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(22) +#else +RET(12) +#endif +} + +// TAS +OPCODE(0x4AF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(24) +#else +RET(14) +#endif +} + +// TAS +OPCODE(0x4AF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(22) +#else +RET(12) +#endif +} + +// TAS +OPCODE(0x4AF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(26) +#else +RET(16) +#endif +} + +// TAS +OPCODE(0x4ADF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(8) +#endif +} + +// TAS +OPCODE(0x4AE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + +#ifdef PICODRIVE_HACK + if (g_m68kcontext == &PicoCpuFS68k) { + res |= 0x80; + WRITE_BYTE_F(adr, res); + } +#endif + + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(8) +#endif +} + +// ILLEGAL +OPCODE(0x4AFC) +{ + SET_PC(execute_exception(M68K_ILLEGAL_INSTRUCTION_EX, GET_PC-2, GET_SR)); +RET(0) +} + +// ILLEGAL A000-AFFF +OPCODE(0xA000) +{ + SET_PC(execute_exception(M68K_1010_EX, GET_PC-2, GET_SR)); +RET(0) +} + +// ILLEGAL F000-FFFF +OPCODE(0xF000) +{ + SET_PC(execute_exception(M68K_1111_EX, GET_PC-2, GET_SR)); +RET(0) // 4 already taken by exc. handler +} + +// MOVEMaR +OPCODE(0x4C90) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(16) +#endif +} + +// MOVEMaR +OPCODE(0x4C98) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + AREG((Opcode >> 0) & 7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +RET(12) +} + +// MOVEMaR +OPCODE(0x4CA8) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(24) +#endif +} + +// MOVEMaR +OPCODE(0x4CB0) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(28) +#endif +} + +// MOVEMaR +OPCODE(0x4CB8) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(24) +#endif +} + +// MOVEMaR +OPCODE(0x4CB9) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + FETCH_LONG(adr); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(32) +#endif +} + +// MOVEMaR +OPCODE(0x4CBA) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = GET_SWORD + GET_PC; + PC++; + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(24) +#endif +} + +// MOVEMaR +OPCODE(0x4CBB) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = GET_PC; + DECODE_EXT_WORD + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(28) +#endif +} + +// MOVEMaR +OPCODE(0x4C9F) +{ + u32 adr, res; + u32 src, dst; + + s32 *psrc; + + FETCH_WORD(res); + adr = AREG(7); + psrc = &DREGs32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READSX_WORD_F(adr, *psrc) + adr += 2; + } + psrc++; + } while (res >>= 1); + AREG(7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +RET(12) +} + +// MOVEMaR +OPCODE(0x4CD0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(20) +#endif +} + +// MOVEMaR +OPCODE(0x4CD8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + AREG((Opcode >> 0) & 7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +RET(12) +} + +// MOVEMaR +OPCODE(0x4CE8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(28) +#endif +} + +// MOVEMaR +OPCODE(0x4CF0) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(32) +#endif +} + +// MOVEMaR +OPCODE(0x4CF8) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_SWORD(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(28) +#endif +} + +// MOVEMaR +OPCODE(0x4CF9) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + FETCH_LONG(adr); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(36) +#endif +} + +// MOVEMaR +OPCODE(0x4CFA) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = GET_SWORD + GET_PC; + PC++; + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(28) +#endif +} + +// MOVEMaR +OPCODE(0x4CFB) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = GET_PC; + DECODE_EXT_WORD + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(32) +#endif +} + +// MOVEMaR +OPCODE(0x4CDF) +{ + u32 adr, res; + u32 src, dst; + + u32 *psrc; + + FETCH_WORD(res); + adr = AREG(7); + psrc = &DREGu32(0); + dst = adr; + PRE_IO + do + { + if (res & 1) + { + READ_LONG_F(adr, *psrc) + adr += 4; + } + psrc++; + } while (res >>= 1); + AREG(7) = adr; + POST_IO + m68kcontext.io_cycle_counter -= (adr - dst) * 2; +RET(12) +} + +// TRAP +OPCODE(0x4E40) +{ + SET_PC(execute_exception(M68K_TRAP_BASE_EX + (Opcode & 0xF), GET_PC, GET_SR)); +RET(4) +} + +// LINK +OPCODE(0x4E50) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + PRE_IO + PUSH_32_F(res) + res = AREG(7); + AREG((Opcode >> 0) & 7) = res; + FETCH_SWORD(res); + AREG(7) += res; + POST_IO +RET(16) +} + +// LINKA7 +OPCODE(0x4E57) +{ + u32 adr, res; + u32 src, dst; + + AREG(7) -= 4; + PRE_IO + WRITE_LONG_DEC_F(AREG(7), AREG(7)) + FETCH_SWORD(res); + AREG(7) += res; + POST_IO +RET(16) +} + +// ULNK +OPCODE(0x4E58) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu32((Opcode >> 0) & 7); + AREG(7) = src + 4; + PRE_IO + READ_LONG_F(src, res) + AREG((Opcode >> 0) & 7) = res; + POST_IO +RET(12) +} + +// ULNKA7 +OPCODE(0x4E5F) +{ + u32 adr, res; + u32 src, dst; + + PRE_IO + READ_LONG_F(AREG(7), AREG(7)) + POST_IO +RET(12) +} + +// MOVEAUSP +OPCODE(0x4E60) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_S) + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } + res = AREGu32((Opcode >> 0) & 7); + ASP = res; +RET(4) +} + +// MOVEUSPA +OPCODE(0x4E68) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_S) + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } + res = ASP; + AREG((Opcode >> 0) & 7) = res; +RET(4) +} + +// RESET +OPCODE(0x4E70) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_S) + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } + PRE_IO + if (m68kcontext.reset_handler) m68kcontext.reset_handler(); +// CPU->Reset_CallBack(); + POST_IO +RET(132) +} + +// NOP +OPCODE(0x4E71) +{ +RET(4) +} + +// STOP +OPCODE(0x4E72) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_S) + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } + FETCH_WORD(res); + res &= M68K_SR_MASK; + SET_SR(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + m68kcontext.execinfo |= FM68K_HALTED; +RET0() +} + +// RTE +OPCODE(0x4E73) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_S) + { + SET_PC(execute_exception(M68K_PRIVILEGE_VIOLATION_EX, GET_PC-2, GET_SR)); + RET(4) + } + PRE_IO + POP_16_F(res) + SET_SR(res) + POP_32_F(res) + SET_PC(res) + if (!flag_S) + { + res = AREG(7); + AREG(7) = ASP; + ASP = res; + } + POST_IO + m68kcontext.execinfo &= ~(FM68K_EMULATE_GROUP_0|FM68K_EMULATE_TRACE|FM68K_DO_TRACE); + CHECK_INT_TO_JUMP(20) +RET(20) +} + +// RTS +OPCODE(0x4E75) +{ + u32 adr, res; + u32 src, dst; + + PRE_IO + POP_32_F(res) + SET_PC(res) + CHECK_BRANCH_EXCEPTION(res) + POST_IO +RET(16) +} + +// TRAPV +OPCODE(0x4E76) +{ + if (flag_V & 0x80) + SET_PC(execute_exception(M68K_TRAPV_EX, GET_PC, GET_SR)); +RET(4) +} + +// RTR +OPCODE(0x4E77) +{ + u32 adr, res; + u32 src, dst; + + PRE_IO + POP_16_F(res) + SET_CCR(res) + POP_32_F(res) + SET_PC(res) + CHECK_BRANCH_EXCEPTION(res) + POST_IO +RET(20) +} + +// JSR +OPCODE(0x4E90) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(16) +} + +// JSR +OPCODE(0x4EA8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(18) +} + +// JSR +OPCODE(0x4EB0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(22) +} + +// JSR +OPCODE(0x4EB8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(18) +} + +// JSR +OPCODE(0x4EB9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(20) +} + +// JSR +OPCODE(0x4EBA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(18) +} + +// JSR +OPCODE(0x4EBB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + { + u32 oldPC; + + oldPC = GET_PC; + PRE_IO + PUSH_32_F(oldPC) + } + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) + POST_IO +RET(22) +} + +// JMP +OPCODE(0x4ED0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(8) +} + +// JMP +OPCODE(0x4EE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(10) +} + +// JMP +OPCODE(0x4EF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(14) +} + +// JMP +OPCODE(0x4EF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(10) +} + +// JMP +OPCODE(0x4EF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(12) +} + +// JMP +OPCODE(0x4EFA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(10) +} + +// JMP +OPCODE(0x4EFB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + SET_PC(adr) + CHECK_BRANCH_EXCEPTION(adr) +RET(14) +} + +// CHK +OPCODE(0x4180) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } +RET(10) +} + +// CHK +OPCODE(0x4190) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(14) +} + +// CHK +OPCODE(0x4198) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(14) +} + +// CHK +OPCODE(0x41A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(16) +} + +// CHK +OPCODE(0x41A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(18) +} + +// CHK +OPCODE(0x41B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(20) +} + +// CHK +OPCODE(0x41B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(18) +} + +// CHK +OPCODE(0x41B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(22) +} + +// CHK +OPCODE(0x41BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(18) +} + +// CHK +OPCODE(0x41BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(20) +} + +// CHK +OPCODE(0x41BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(14) +} + +// CHK +OPCODE(0x419F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(14) +} + +// CHK +OPCODE(0x41A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + if (((s32)res < 0) || (res > src)) + { + flag_N = res >> 8; + SET_PC(execute_exception(M68K_CHK_EX, GET_PC, GET_SR)); + } + POST_IO +RET(16) +} + +// LEA +OPCODE(0x41D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(4) +} + +// LEA +OPCODE(0x41E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// LEA +OPCODE(0x41F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// LEA +OPCODE(0x41F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// LEA +OPCODE(0x41F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// LEA +OPCODE(0x41FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// LEA +OPCODE(0x41FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + res = adr; + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// STCC +OPCODE(0x50C0) +{ + u32 adr, res; + u32 src, dst; + + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) +} + +// STCC +OPCODE(0x51C0) +{ + u32 adr, res; + u32 src, dst; + + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x52C0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x53C0) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x54C0) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_C & 0x100)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x55C0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_C & 0x100) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x56C0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x57C0) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_NotZ) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x58C0) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_V & 0x80)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x59C0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_V & 0x80) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5AC0) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_N & 0x80)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5BC0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_N & 0x80) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5CC0) +{ + u32 adr, res; + u32 src, dst; + + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5DC0) +{ + u32 adr, res; + u32 src, dst; + + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5EC0) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x5FC0) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(4) +} + +// STCC +OPCODE(0x50D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x51D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x52D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x53D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x54D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x55D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x56D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x57D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x58D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x59D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5AD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5BD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5CD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5DD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5ED0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5FD0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x50D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x51D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x52D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x53D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x54D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x55D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x56D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x57D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x58D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x59D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5AD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5BD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5CD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5DD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5ED8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5FD8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x50E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x51E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x52E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x53E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x54E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x55E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x56E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x57E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x58E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x59E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5AE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5BE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5CE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5DE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5EE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5FE0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x50E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x51E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x52E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x53E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x54E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x55E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x56E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x57E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x58E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x59E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5AE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5BE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5CE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5DE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5EE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5FE8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x50F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x51F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x52F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x53F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x54F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x55F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x56F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x57F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x58F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x59F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5AF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5BF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5CF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5DF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5EF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x5FF0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(18) +} + +// STCC +OPCODE(0x50F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x51F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x52F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x53F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x54F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x55F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x56F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x57F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x58F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x59F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5AF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5BF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5CF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5DF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5EF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x5FF8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(16) +} + +// STCC +OPCODE(0x50F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x51F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x52F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x53F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x54F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x55F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x56F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x57F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x58F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x59F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5AF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5BF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5CF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5DF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5EF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x5FF9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(20) +} + +// STCC +OPCODE(0x50DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x51DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x52DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x53DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x54DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x55DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x56DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x57DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x58DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x59DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5ADF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5BDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5CDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5DDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5EDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x5FDF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(12) +} + +// STCC +OPCODE(0x50E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x51E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x52E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x53E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x54E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (!(flag_C & 0x100)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x55E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_C & 0x100) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x56E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x57E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (!flag_NotZ) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x58E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (!(flag_V & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x59E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_V & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5AE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (!(flag_N & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5BE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_N & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5CE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (!((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5DE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if ((flag_N ^ flag_V) & 0x80) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5EE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// STCC +OPCODE(0x5FE7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = 0xFF; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) + } + res = 0; + PRE_IO + WRITE_BYTE_F(adr, res) + POST_IO + RET(14) +} + +// DBCC +OPCODE(0x50C8) +{ + u32 adr, res; + u32 src, dst; + + PC++; +RET(12) +} + +// DBCC +OPCODE(0x51C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x52C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if ((!flag_NotZ) || (flag_C & 0x100)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x53C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_NotZ && (!(flag_C & 0x100))) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x54C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_C & 0x100) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x55C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (!(flag_C & 0x100)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x56C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (!flag_NotZ) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x57C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_NotZ) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x58C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_V & 0x80) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x59C8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (!(flag_V & 0x80)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5AC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_N & 0x80) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5BC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (!(flag_N & 0x80)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5CC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if ((flag_N ^ flag_V) & 0x80) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5DC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (!((flag_N ^ flag_V) & 0x80)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5EC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// DBCC +OPCODE(0x5FC8) +{ + u32 adr, res; + u32 src, dst; + + NOT_POLLING + + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + res = DREGu16((Opcode >> 0) & 7); + res--; + DREGu16((Opcode >> 0) & 7) = res; + if ((s32)res != -1) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + } + else + { + PC++; + RET(12) + } + PC++; +RET(14) +} + +// ADDQ +OPCODE(0x5000) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu8((Opcode >> 0) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// ADDQ +OPCODE(0x5010) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5018) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5020) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ADDQ +OPCODE(0x5028) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDQ +OPCODE(0x5030) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDQ +OPCODE(0x5038) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDQ +OPCODE(0x5039) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ADDQ +OPCODE(0x501F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5027) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ADDQ +OPCODE(0x5040) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu16((Opcode >> 0) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// ADDQ +OPCODE(0x5048) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = AREGu32((Opcode >> 0) & 7); + res = dst + src; + AREG((Opcode >> 0) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(4) +#else +RET(8) +#endif +} + +// ADDQ +OPCODE(0x5050) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5058) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5060) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ADDQ +OPCODE(0x5068) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDQ +OPCODE(0x5070) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDQ +OPCODE(0x5078) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDQ +OPCODE(0x5079) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ADDQ +OPCODE(0x505F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDQ +OPCODE(0x5067) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ADDQ +OPCODE(0x5080) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu32((Opcode >> 0) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ADDQ +OPCODE(0x5088) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = AREGu32((Opcode >> 0) & 7); + res = dst + src; + AREG((Opcode >> 0) & 7) = res; +RET(8) +} + +// ADDQ +OPCODE(0x5090) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDQ +OPCODE(0x5098) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDQ +OPCODE(0x50A0) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ADDQ +OPCODE(0x50A8) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ADDQ +OPCODE(0x50B0) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// ADDQ +OPCODE(0x50B8) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ADDQ +OPCODE(0x50B9) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ADDQ +OPCODE(0x509F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDQ +OPCODE(0x50A7) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// SUBQ +OPCODE(0x5100) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu8((Opcode >> 0) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// SUBQ +OPCODE(0x5110) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5118) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5120) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// SUBQ +OPCODE(0x5128) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBQ +OPCODE(0x5130) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBQ +OPCODE(0x5138) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBQ +OPCODE(0x5139) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// SUBQ +OPCODE(0x511F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5127) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// SUBQ +OPCODE(0x5140) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu16((Opcode >> 0) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// SUBQ +OPCODE(0x5148) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = AREGu32((Opcode >> 0) & 7); + res = dst - src; + AREG((Opcode >> 0) & 7) = res; +RET(8) +} + +// SUBQ +OPCODE(0x5150) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5158) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5160) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// SUBQ +OPCODE(0x5168) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBQ +OPCODE(0x5170) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBQ +OPCODE(0x5178) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBQ +OPCODE(0x5179) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// SUBQ +OPCODE(0x515F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBQ +OPCODE(0x5167) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// SUBQ +OPCODE(0x5180) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = DREGu32((Opcode >> 0) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// SUBQ +OPCODE(0x5188) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + dst = AREGu32((Opcode >> 0) & 7); + res = dst - src; + AREG((Opcode >> 0) & 7) = res; +RET(8) +} + +// SUBQ +OPCODE(0x5190) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBQ +OPCODE(0x5198) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBQ +OPCODE(0x51A0) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// SUBQ +OPCODE(0x51A8) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// SUBQ +OPCODE(0x51B0) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// SUBQ +OPCODE(0x51B8) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// SUBQ +OPCODE(0x51B9) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// SUBQ +OPCODE(0x519F) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBQ +OPCODE(0x51A7) +{ + u32 adr, res; + u32 src, dst; + + src = (((Opcode >> 9) - 1) & 7) + 1; + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// BCC +OPCODE(0x6201) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!(flag_C & 0x100))) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6301) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || (flag_C & 0x100)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6401) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_C & 0x100)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6501) +{ + u32 adr, res; + u32 src, dst; + + if (flag_C & 0x100) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6601) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6701) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_NotZ) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6801) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_V & 0x80)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6901) +{ + u32 adr, res; + u32 src, dst; + + if (flag_V & 0x80) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6A01) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_N & 0x80)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6B01) +{ + u32 adr, res; + u32 src, dst; + + if (flag_N & 0x80) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6C01) +{ + u32 adr, res; + u32 src, dst; + + if (!((flag_N ^ flag_V) & 0x80)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6D01) +{ + u32 adr, res; + u32 src, dst; + + if ((flag_N ^ flag_V) & 0x80) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6E01) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC +OPCODE(0x6F01) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + PC += ((s8)(Opcode & 0xFE)) >> 1; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +// BCC16 +OPCODE(0x6200) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!(flag_C & 0x100))) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6300) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || (flag_C & 0x100)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6400) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_C & 0x100)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6500) +{ + u32 adr, res; + u32 src, dst; + + if (flag_C & 0x100) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6600) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6700) +{ + u32 adr, res; + u32 src, dst; + + if (!flag_NotZ) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6800) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_V & 0x80)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6900) +{ + u32 adr, res; + u32 src, dst; + + if (flag_V & 0x80) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6A00) +{ + u32 adr, res; + u32 src, dst; + + if (!(flag_N & 0x80)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6B00) +{ + u32 adr, res; + u32 src, dst; + + if (flag_N & 0x80) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6C00) +{ + u32 adr, res; + u32 src, dst; + + if (!((flag_N ^ flag_V) & 0x80)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6D00) +{ + u32 adr, res; + u32 src, dst; + + if ((flag_N ^ flag_V) & 0x80) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6E00) +{ + u32 adr, res; + u32 src, dst; + + if (flag_NotZ && (!((flag_N ^ flag_V) & 0x80))) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BCC16 +OPCODE(0x6F00) +{ + u32 adr, res; + u32 src, dst; + + if ((!flag_NotZ) || ((flag_N ^ flag_V) & 0x80)) + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + RET(10) + } + PC++; +RET(12) +} + +// BRA +OPCODE(0x6001) +{ +#ifdef FAMEC_CHECK_BRANCHES + u32 newPC = GET_PC; + s8 offs=Opcode; + newPC += offs; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(offs) +#else + PC += ((s8)(Opcode & 0xFE)) >> 1; +#endif +RET(10) +} + +// BRA16 +OPCODE(0x6000) +{ + u32 adr, res; + u32 src, dst; + + { + u32 newPC; + + newPC = GET_PC; + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + } +RET(10) +} + +// BSR +OPCODE(0x6101) +{ + u32 adr, res; + u32 src, dst; + u32 oldPC; + s8 offs; + + PRE_IO + + oldPC = GET_PC; + PUSH_32_F(oldPC) +#ifdef FAMEC_CHECK_BRANCHES + offs = Opcode; + oldPC += offs; + SET_PC(oldPC); + CHECK_BRANCH_EXCEPTION(offs) +#else + PC += ((s8)(Opcode & 0xFE)) >> 1; +#endif + POST_IO +RET(18) +} + +// BSR16 +OPCODE(0x6100) +{ + u32 adr, res; + u32 src, dst; + + PRE_IO + { + u32 oldPC, newPC; + + newPC = GET_PC; + oldPC = newPC + 2; + PUSH_32_F(oldPC) + newPC += GET_SWORD; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(newPC) + } + POST_IO +RET(18) +} + +// MOVEQ +OPCODE(0x7000) +{ + u32 adr, res; + u32 src, dst; + + res = (s32)(s8)Opcode; + flag_C = flag_V = 0; + flag_N = flag_NotZ = res; + DREGu32((Opcode >> 9) & 7) = res; +RET(4) +} + +// ORaD +OPCODE(0x8000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// ORaD +OPCODE(0x8010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ORaD +OPCODE(0x8028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x8030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x8038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x8039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ORaD +OPCODE(0x803A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x803B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x803C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(8) +} + +// ORaD +OPCODE(0x801F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ORaD +OPCODE(0x8040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// ORaD +OPCODE(0x8050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ORaD +OPCODE(0x8068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x8070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x8078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x8079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ORaD +OPCODE(0x807A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ORaD +OPCODE(0x807B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x807C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(8) +} + +// ORaD +OPCODE(0x805F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ORaD +OPCODE(0x8067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ORaD +OPCODE(0x8080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// ORaD +OPCODE(0x8090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x8098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x80A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ORaD +OPCODE(0x80A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ORaD +OPCODE(0x80B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ORaD +OPCODE(0x80B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ORaD +OPCODE(0x80B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// ORaD +OPCODE(0x80BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ORaD +OPCODE(0x80BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ORaD +OPCODE(0x80BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(16) +} + +// ORaD +OPCODE(0x809F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ORaD +OPCODE(0x80A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ORDa +OPCODE(0x8110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ORDa +OPCODE(0x8128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ORDa +OPCODE(0x8130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ORDa +OPCODE(0x8138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ORDa +OPCODE(0x8139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ORDa +OPCODE(0x811F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ORDa +OPCODE(0x8150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ORDa +OPCODE(0x8168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ORDa +OPCODE(0x8170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ORDa +OPCODE(0x8178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ORDa +OPCODE(0x8179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ORDa +OPCODE(0x815F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ORDa +OPCODE(0x8167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ORDa +OPCODE(0x8190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ORDa +OPCODE(0x8198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ORDa +OPCODE(0x81A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ORDa +OPCODE(0x81A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ORDa +OPCODE(0x81B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// ORDa +OPCODE(0x81B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ORDa +OPCODE(0x81B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ORDa +OPCODE(0x819F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ORDa +OPCODE(0x81A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res |= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// SBCD +OPCODE(0x8100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res -= 6; + res += (dst & 0xF0) - (src & 0xF0); + if (res > 0x99) + { + res += 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(6) +} + +// SBCDM +OPCODE(0x8108) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res -= 6; + res += (dst & 0xF0) - (src & 0xF0); + if (res > 0x99) + { + res += 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SBCD7M +OPCODE(0x810F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res -= 6; + res += (dst & 0xF0) - (src & 0xF0); + if (res > 0x99) + { + res += 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SBCDM7 +OPCODE(0x8F08) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res -= 6; + res += (dst & 0xF0) - (src & 0xF0); + if (res > 0x99) + { + res += 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SBCD7M7 +OPCODE(0x8F0F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) - (src & 0xF) - ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res -= 6; + res += (dst & 0xF0) - (src & 0xF0); + if (res > 0x99) + { + res += 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// DIVU +OPCODE(0x80C0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(140) +#else +RET(10) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(140) +#else +RET(70) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(140) +#else +RET(90) +#endif +} + +// DIVU +OPCODE(0x80D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(14) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else + RET(74) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(94) +#endif +} + +// DIVU +OPCODE(0x80D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(14) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else + RET(74) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(94) +#endif +} + +// DIVU +OPCODE(0x80E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else +RET(16) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else + RET(76) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else +RET(96) +#endif +} + +// DIVU +OPCODE(0x80E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(18) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else + RET(78) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(98) +#endif +} + +// DIVU +OPCODE(0x80F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(150) +#else +RET(20) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(150) +#else + RET(80) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(150) +#else +RET(100) +#endif +} + +// DIVU +OPCODE(0x80F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(18) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else + RET(78) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(98) +#endif +} + +// DIVU +OPCODE(0x80F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(162) +#else +RET(22) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(162) +#else + RET(82) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(162) +#else +RET(102) +#endif +} + +// DIVU +OPCODE(0x80FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(18) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else + RET(78) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(148) +#else +RET(98) +#endif +} + +// DIVU +OPCODE(0x80FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(160) +#else +RET(20) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(160) +#else + RET(80) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(160) +#else +RET(100) +#endif +} + +// DIVU +OPCODE(0x80FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(14) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else + RET(74) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(94) +#endif +} + +// DIVU +OPCODE(0x80DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(14) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else + RET(74) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(144) +#else +RET(94) +#endif +} + +// DIVU +OPCODE(0x80E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else +RET(16) +#endif + } + dst = DREGu32((Opcode >> 9) & 7); + { + u32 q, r; + + q = dst / src; + r = dst % src; + + if (q & 0xFFFF0000) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else + RET(76) +#endif + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +RET(146) +#else +RET(96) +#endif +} + +// DIVS +OPCODE(0x81C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs16((Opcode >> 0) & 7); + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81C0; +#endif + RET(10) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81C0; +#endif + RET(50) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81C0; +#endif + RET(80) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81C0: m68kcontext.io_cycle_counter -= 50; +#endif +RET(108) +} + +// DIVS +OPCODE(0x81D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D0; +#endif + RET(14) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D0; +#endif + RET(54) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D0; +#endif + RET(84) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81D0: m68kcontext.io_cycle_counter -= 50; +#endif +RET(112) +} + +// DIVS +OPCODE(0x81D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D8; +#endif + RET(14) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D8; +#endif + RET(54) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81D8; +#endif + RET(84) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81D8: m68kcontext.io_cycle_counter -= 50; +#endif +RET(112) +} + +// DIVS +OPCODE(0x81E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E0; +#endif + RET(16) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E0; +#endif + RET(56) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E0; +#endif + RET(86) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81E0: m68kcontext.io_cycle_counter -= 50; +#endif +RET(114) +} + +// DIVS +OPCODE(0x81E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E8; +#endif + RET(18) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E8; +#endif + RET(58) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E8; +#endif + RET(88) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81E8: m68kcontext.io_cycle_counter -= 50; +#endif +RET(116) +} + +// DIVS +OPCODE(0x81F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F0; +#endif + RET(20) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F0; +#endif + RET(60) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F0; +#endif + RET(90) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81F0: m68kcontext.io_cycle_counter -= 50; +#endif +RET(118) +} + +// DIVS +OPCODE(0x81F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F8; +#endif + RET(18) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F8; +#endif + RET(58) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F8; +#endif + RET(88) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81F8: m68kcontext.io_cycle_counter -= 50; +#endif +RET(116) +} + +// DIVS +OPCODE(0x81F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F9; +#endif + RET(22) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F9; +#endif + RET(62) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81F9; +#endif + RET(92) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81F9: m68kcontext.io_cycle_counter -= 50; +#endif +RET(120) +} + +// DIVS +OPCODE(0x81FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FA; +#endif + RET(18) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FA; +#endif + RET(58) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FA; +#endif + RET(88) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81FA: m68kcontext.io_cycle_counter -= 50; +#endif +RET(116) +} + +// DIVS +OPCODE(0x81FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FB; +#endif + RET(20) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FB; +#endif + RET(60) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FB; +#endif + RET(90) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81FB: m68kcontext.io_cycle_counter -= 50; +#endif +RET(118) +} + +// DIVS +OPCODE(0x81FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(src); + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FC; +#endif + RET(14) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FC; +#endif + RET(54) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81FC; +#endif + RET(84) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81FC: m68kcontext.io_cycle_counter -= 50; +#endif +RET(112) +} + +// DIVS +OPCODE(0x81DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81DF; +#endif + RET(14) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81DF; +#endif + RET(54) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81DF; +#endif + RET(84) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81DF: m68kcontext.io_cycle_counter -= 50; +#endif +RET(112) +} + +// DIVS +OPCODE(0x81E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + if (src == 0) + { + SET_PC(execute_exception(M68K_ZERO_DIVIDE_EX, GET_PC, GET_SR)); +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E7; +#endif + RET(16) + } + dst = DREGu32((Opcode >> 9) & 7); + if ((dst == 0x80000000) && (src == (u32)-1)) + { + flag_NotZ = flag_N = 0; + flag_V = flag_C = 0; + res = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E7; +#endif + RET(56) + } + { + s32 q, r; + + q = (s32)dst / (s32)src; + r = (s32)dst % (s32)src; + + if ((q > 0x7FFF) || (q < -0x8000)) + { + flag_V = M68K_SR_V; +#ifdef USE_CYCLONE_TIMING_DIV +goto end81E7; +#endif + RET(86) + } + q &= 0x0000FFFF; + flag_NotZ = q; + flag_N = q >> 8; + flag_V = flag_C = 0; + res = q | (r << 16); + DREGu32((Opcode >> 9) & 7) = res; + } +#ifdef USE_CYCLONE_TIMING_DIV +end81E7: m68kcontext.io_cycle_counter -= 50; +#endif +RET(114) +} + +// SUBaD +OPCODE(0x9000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// SUBaD +#if 0 +OPCODE(0x9008) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +*/ +RET(4) +} +#endif + +// SUBaD +OPCODE(0x9010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// SUBaD +OPCODE(0x9028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x9030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x9038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x9039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// SUBaD +OPCODE(0x903A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x903B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x903C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBaD +OPCODE(0x901F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// SUBaD +OPCODE(0x9040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// SUBaD +OPCODE(0x9048) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// SUBaD +OPCODE(0x9050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// SUBaD +OPCODE(0x9068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x9070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x9078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x9079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// SUBaD +OPCODE(0x907A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// SUBaD +OPCODE(0x907B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x907C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBaD +OPCODE(0x905F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// SUBaD +OPCODE(0x9067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// SUBaD +OPCODE(0x9080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBaD +OPCODE(0x9088) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBaD +OPCODE(0x9090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x9098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x90A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// SUBaD +OPCODE(0x90A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBaD +OPCODE(0x90B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// SUBaD +OPCODE(0x90B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBaD +OPCODE(0x90B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// SUBaD +OPCODE(0x90BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBaD +OPCODE(0x90BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// SUBaD +OPCODE(0x90BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(16) +} + +// SUBaD +OPCODE(0x909F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBaD +OPCODE(0x90A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// SUBDa +OPCODE(0x9110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// SUBDa +OPCODE(0x9128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBDa +OPCODE(0x9130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBDa +OPCODE(0x9138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// SUBDa +OPCODE(0x9139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// SUBDa +OPCODE(0x911F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// SUBDa +OPCODE(0x9150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// SUBDa +OPCODE(0x9168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBDa +OPCODE(0x9170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBDa +OPCODE(0x9178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// SUBDa +OPCODE(0x9179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// SUBDa +OPCODE(0x915F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// SUBDa +OPCODE(0x9167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// SUBDa +OPCODE(0x9190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBDa +OPCODE(0x9198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBDa +OPCODE(0x91A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// SUBDa +OPCODE(0x91A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// SUBDa +OPCODE(0x91B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// SUBDa +OPCODE(0x91B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// SUBDa +OPCODE(0x91B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// SUBDa +OPCODE(0x919F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// SUBDa +OPCODE(0x91A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// SUBX +OPCODE(0x9100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src - ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ |= res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// SUBX +OPCODE(0x9140) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src - ((flag_X >> 8) & 1); + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// SUBX +OPCODE(0x9180) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBXM +OPCODE(0x9108) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBXM +OPCODE(0x9148) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + READ_WORD_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBXM +OPCODE(0x9188) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + READ_LONG_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// SUBX7M +OPCODE(0x910F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBX7M +OPCODE(0x914F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + READ_WORD_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBX7M +OPCODE(0x918F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + READ_LONG_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// SUBXM7 +OPCODE(0x9F08) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBXM7 +OPCODE(0x9F48) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_WORD_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBXM7 +OPCODE(0x9F88) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7) - 4; + AREG(7) = adr; + READ_LONG_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// SUBX7M7 +OPCODE(0x9F0F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// SUBX7M7 +OPCODE(0x9F4F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_WORD_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// SUBX7M7 +OPCODE(0x9F8F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7) - 4; + AREG(7) = adr; + READ_LONG_F(adr, dst) + res = dst - src - ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// SUBA +OPCODE(0x90C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBA +OPCODE(0x90C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// SUBA +OPCODE(0x90D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// SUBA +OPCODE(0x90D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// SUBA +OPCODE(0x90E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(12) +#endif +} + +// SUBA +OPCODE(0x90E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// SUBA +OPCODE(0x90F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(16) +#endif +} + +// SUBA +OPCODE(0x90F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// SUBA +OPCODE(0x90F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(18) +#endif +} + +// SUBA +OPCODE(0x90FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// SUBA +OPCODE(0x90FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(16) +#endif +} + +// SUBA +OPCODE(0x90FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// SUBA +OPCODE(0x90DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// SUBA +OPCODE(0x90E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(12) +#endif +} + +// SUBA +OPCODE(0x91C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(6) +#endif +} + +// SUBA +OPCODE(0x91C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(6) +#endif +} + +// SUBA +OPCODE(0x91D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBA +OPCODE(0x91D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBA +OPCODE(0x91E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// SUBA +OPCODE(0x91E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBA +OPCODE(0x91F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// SUBA +OPCODE(0x91F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBA +OPCODE(0x91F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// SUBA +OPCODE(0x91FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// SUBA +OPCODE(0x91FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// SUBA +OPCODE(0x91FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// SUBA +OPCODE(0x91DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// SUBA +OPCODE(0x91E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// CMP +OPCODE(0xB000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; +RET(4) +} + +// CMP +#if 0 +OPCODE(0xB008) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; +*/ +RET(4) +} +#endif + +// CMP +OPCODE(0xB010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(10) +} + +// CMP +OPCODE(0xB028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(16) +} + +// CMP +OPCODE(0xB03A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB03B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB03C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; +RET(8) +} + +// CMP +OPCODE(0xB01F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(10) +} + +// CMP +OPCODE(0xB040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; +RET(4) +} + +// CMP +OPCODE(0xB048) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; +RET(4) +} + +// CMP +OPCODE(0xB050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(10) +} + +// CMP +OPCODE(0xB068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(16) +} + +// CMP +OPCODE(0xB07A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMP +OPCODE(0xB07B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB07C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; +RET(8) +} + +// CMP +OPCODE(0xB05F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(8) +} + +// CMP +OPCODE(0xB067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(10) +} + +// CMP +OPCODE(0xB080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMP +OPCODE(0xB088) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMP +OPCODE(0xB090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB0A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// CMP +OPCODE(0xB0A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMP +OPCODE(0xB0B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMP +OPCODE(0xB0B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMP +OPCODE(0xB0B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(22) +} + +// CMP +OPCODE(0xB0BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMP +OPCODE(0xB0BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMP +OPCODE(0xB0BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(14) +} + +// CMP +OPCODE(0xB09F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMP +OPCODE(0xB0A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// CMPM +OPCODE(0xB108) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMPM +OPCODE(0xB148) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMPM +OPCODE(0xB188) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMP7M +OPCODE(0xB10F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 1; + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMP7M +OPCODE(0xB14F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 2; + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMP7M +OPCODE(0xB18F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) += 4; + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPM7 +OPCODE(0xBF08) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7); + AREG(7) += 2; + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMPM7 +OPCODE(0xBF48) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7); + AREG(7) += 2; + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMPM7 +OPCODE(0xBF88) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7); + AREG(7) += 4; + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMP7M7 +OPCODE(0xBF0F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7); + AREG(7) += 2; + READ_BYTE_F(adr, dst) + res = dst - src; + flag_N = flag_C = res; + flag_V = (src ^ dst) & (res ^ dst); + flag_NotZ = res & 0xFF; + POST_IO +RET(12) +} + +// CMP7M7 +OPCODE(0xBF4F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7); + AREG(7) += 2; + READ_WORD_F(adr, dst) + res = dst - src; + flag_V = ((src ^ dst) & (res ^ dst)) >> 8; + flag_N = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + POST_IO +RET(12) +} + +// CMP7M7 +OPCODE(0xBF8F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7); + AREG(7) += 4; + READ_LONG_F(adr, dst) + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + res = DREGu8((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(4) +} + +// EORDa +OPCODE(0xB110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// EORDa +OPCODE(0xB128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// EORDa +OPCODE(0xB130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// EORDa +OPCODE(0xB138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// EORDa +OPCODE(0xB139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB11F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// EORDa +OPCODE(0xB140) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + res = DREGu16((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 0) & 7) = res; +RET(4) +} + +// EORDa +OPCODE(0xB150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// EORDa +OPCODE(0xB168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// EORDa +OPCODE(0xB170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// EORDa +OPCODE(0xB178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// EORDa +OPCODE(0xB179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB15F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// EORDa +OPCODE(0xB167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// EORDa +OPCODE(0xB180) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + res = DREGu32((Opcode >> 0) & 7); + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// EORDa +OPCODE(0xB190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB1A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// EORDa +OPCODE(0xB1A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// EORDa +OPCODE(0xB1B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// EORDa +OPCODE(0xB1B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// EORDa +OPCODE(0xB1B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// EORDa +OPCODE(0xB19F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// EORDa +OPCODE(0xB1A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res ^= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// CMPA +OPCODE(0xB0C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMPA +OPCODE(0xB0C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMPA +OPCODE(0xB0D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(10) +} + +// CMPA +OPCODE(0xB0D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(10) +} + +// CMPA +OPCODE(0xB0E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(12) +} + +// CMPA +OPCODE(0xB0E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB0F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// CMPA +OPCODE(0xB0F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB0F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMPA +OPCODE(0xB0FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB0FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// CMPA +OPCODE(0xB0FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(10) +} + +// CMPA +OPCODE(0xB0DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(10) +} + +// CMPA +OPCODE(0xB0E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(12) +} + +// CMPA +OPCODE(0xB1C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMPA +OPCODE(0xB1C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(6) +} + +// CMPA +OPCODE(0xB1D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB1D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB1E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// CMPA +OPCODE(0xB1E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMPA +OPCODE(0xB1F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPA +OPCODE(0xB1F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMPA +OPCODE(0xB1F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(22) +} + +// CMPA +OPCODE(0xB1FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(18) +} + +// CMPA +OPCODE(0xB1FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(20) +} + +// CMPA +OPCODE(0xB1FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; +RET(14) +} + +// CMPA +OPCODE(0xB1DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(14) +} + +// CMPA +OPCODE(0xB1E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst - src; + flag_NotZ = res; + flag_C = ((src & res & 1) + (src >> 1) + (res >> 1)) >> 23; + flag_V = ((src ^ dst) & (res ^ dst)) >> 24; + flag_N = res >> 24; + POST_IO +RET(16) +} + +// ANDaD +OPCODE(0xC000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// ANDaD +OPCODE(0xC010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ANDaD +OPCODE(0xC028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ANDaD +OPCODE(0xC03A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC03B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC03C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(8) +} + +// ANDaD +OPCODE(0xC01F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + res = DREGu8((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ANDaD +OPCODE(0xC040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// ANDaD +OPCODE(0xC050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ANDaD +OPCODE(0xC068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ANDaD +OPCODE(0xC07A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ANDaD +OPCODE(0xC07B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC07C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; +RET(8) +} + +// ANDaD +OPCODE(0xC05F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ANDaD +OPCODE(0xC067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ANDaD +OPCODE(0xC080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// ANDaD +OPCODE(0xC090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC0A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ANDaD +OPCODE(0xC0A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ANDaD +OPCODE(0xC0B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ANDaD +OPCODE(0xC0B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ANDaD +OPCODE(0xC0B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// ANDaD +OPCODE(0xC0BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ANDaD +OPCODE(0xC0BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ANDaD +OPCODE(0xC0BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(16) +} + +// ANDaD +OPCODE(0xC09F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ANDaD +OPCODE(0xC0A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + res = DREGu32((Opcode >> 9) & 7); + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ANDDa +OPCODE(0xC110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ANDDa +OPCODE(0xC128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ANDDa +OPCODE(0xC130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ANDDa +OPCODE(0xC138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ANDDa +OPCODE(0xC139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ANDDa +OPCODE(0xC11F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ANDDa +OPCODE(0xC150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ANDDa +OPCODE(0xC168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ANDDa +OPCODE(0xC170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ANDDa +OPCODE(0xC178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ANDDa +OPCODE(0xC179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ANDDa +OPCODE(0xC15F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ANDDa +OPCODE(0xC167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 8; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ANDDa +OPCODE(0xC190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ANDDa +OPCODE(0xC198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ANDDa +OPCODE(0xC1A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ANDDa +OPCODE(0xC1A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ANDDa +OPCODE(0xC1B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// ANDDa +OPCODE(0xC1B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ANDDa +OPCODE(0xC1B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ANDDa +OPCODE(0xC19F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ANDDa +OPCODE(0xC1A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, res) + res &= src; + flag_C = 0; + flag_V = 0; + flag_NotZ = res; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ABCD +OPCODE(0xC100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res += 6; + res += (dst & 0xF0) + (src & 0xF0); + if (res > 0x99) + { + res -= 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + DREGu8((Opcode >> 9) & 7) = res; +RET(6) +} + +// ABCDM +OPCODE(0xC108) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res += 6; + res += (dst & 0xF0) + (src & 0xF0); + if (res > 0x99) + { + res -= 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ABCD7M +OPCODE(0xC10F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res += 6; + res += (dst & 0xF0) + (src & 0xF0); + if (res > 0x99) + { + res -= 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ABCDM7 +OPCODE(0xCF08) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res += 6; + res += (dst & 0xF0) + (src & 0xF0); + if (res > 0x99) + { + res -= 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ABCD7M7 +OPCODE(0xCF0F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = (dst & 0xF) + (src & 0xF) + ((flag_X >> M68K_SR_X_SFT) & 1); + if (res > 9) res += 6; + res += (dst & 0xF0) + (src & 0xF0); + if (res > 0x99) + { + res -= 0xA0; + flag_X = flag_C = M68K_SR_C; + } + else flag_X = flag_C = 0; + flag_NotZ |= res & 0xFF; + flag_N = res; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// MULU +OPCODE(0xC0C0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(54) +#else +RET(50) +#endif +} + +// MULU +OPCODE(0xC0D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULU +OPCODE(0xC0D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULU +OPCODE(0xC0E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(60) +#else +RET(56) +#endif +} + +// MULU +OPCODE(0xC0E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULU +OPCODE(0xC0F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(64) +#else +RET(60) +#endif +} + +// MULU +OPCODE(0xC0F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULU +OPCODE(0xC0F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(66) +#else +RET(62) +#endif +} + +// MULU +OPCODE(0xC0FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULU +OPCODE(0xC0FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(64) +#else +RET(60) +#endif +} + +// MULU +OPCODE(0xC0FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULU +OPCODE(0xC0DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULU +OPCODE(0xC0E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + res = DREGu16((Opcode >> 9) & 7); + res *= src; + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(60) +#else +RET(56) +#endif +} + +// MULS +OPCODE(0xC1C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs16((Opcode >> 0) & 7); + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(54) +#else +RET(50) +#endif +} + +// MULS +OPCODE(0xC1D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULS +OPCODE(0xC1D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULS +OPCODE(0xC1E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(60) +#else +RET(56) +#endif +} + +// MULS +OPCODE(0xC1E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULS +OPCODE(0xC1F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(64) +#else +RET(60) +#endif +} + +// MULS +OPCODE(0xC1F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULS +OPCODE(0xC1F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(66) +#else +RET(62) +#endif +} + +// MULS +OPCODE(0xC1FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(62) +#else +RET(58) +#endif +} + +// MULS +OPCODE(0xC1FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(64) +#else +RET(60) +#endif +} + +// MULS +OPCODE(0xC1FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(src); + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULS +OPCODE(0xC1DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(58) +#else +RET(54) +#endif +} + +// MULS +OPCODE(0xC1E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + res = (s32)DREGs16((Opcode >> 9) & 7); + res = ((s32)res) * ((s32)src); + flag_N = res >> 24; + flag_NotZ = res; + flag_V = flag_C = 0; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(60) +#else +RET(56) +#endif +} + +// EXGDD +OPCODE(0xC140) +{ + u32 adr, res; + u32 src, dst; + + res = DREGu32((Opcode >> 0) & 7); + src = DREGu32((Opcode >> 9) & 7); + DREGu32((Opcode >> 9) & 7) = res; + res = src; + DREGu32((Opcode >> 0) & 7) = res; +RET(6) +} + +// EXGAA +OPCODE(0xC148) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + src = AREGu32((Opcode >> 9) & 7); + AREG((Opcode >> 9) & 7) = res; + res = src; + AREG((Opcode >> 0) & 7) = res; +RET(6) +} + +// EXGAD +OPCODE(0xC188) +{ + u32 adr, res; + u32 src, dst; + + res = AREGu32((Opcode >> 0) & 7); + src = DREGu32((Opcode >> 9) & 7); + DREGu32((Opcode >> 9) & 7) = res; + res = src; + AREG((Opcode >> 0) & 7) = res; +RET(6) +} + +// ADDaD +OPCODE(0xD000) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// ADDaD +#if 0 +OPCODE(0xD008) +{ + u32 adr, res; + u32 src, dst; + + // can't read byte from Ax registers ! + m68kcontext.execinfo |= M68K_FAULTED; + m68kcontext.io_cycle_counter = 0; +/* + goto famec_Exec_End; + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +*/ +RET(4) +} +#endif + +// ADDaD +OPCODE(0xD010) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD018) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD020) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ADDaD +OPCODE(0xD028) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD030) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD038) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD039) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ADDaD +OPCODE(0xD03A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD03B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD03C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_BYTE(src); + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDaD +OPCODE(0xD01F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD027) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ADDaD +OPCODE(0xD040) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// ADDaD +OPCODE(0xD048) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// ADDaD +OPCODE(0xD050) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD058) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD060) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ADDaD +OPCODE(0xD068) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD070) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD078) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD079) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ADDaD +OPCODE(0xD07A) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(12) +} + +// ADDaD +OPCODE(0xD07B) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD07C) +{ + u32 adr, res; + u32 src, dst; + + FETCH_WORD(src); + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDaD +OPCODE(0xD05F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(8) +} + +// ADDaD +OPCODE(0xD067) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; + POST_IO +RET(10) +} + +// ADDaD +OPCODE(0xD080) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDaD +OPCODE(0xD088) +{ + u32 adr, res; + u32 src, dst; + + src = AREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDaD +OPCODE(0xD090) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD098) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD0A0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ADDaD +OPCODE(0xD0A8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDaD +OPCODE(0xD0B0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ADDaD +OPCODE(0xD0B8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDaD +OPCODE(0xD0B9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// ADDaD +OPCODE(0xD0BA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDaD +OPCODE(0xD0BB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ADDaD +OPCODE(0xD0BC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(16) +} + +// ADDaD +OPCODE(0xD09F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDaD +OPCODE(0xD0A7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ADDDa +OPCODE(0xD110) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD118) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 1; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD120) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ADDDa +OPCODE(0xD128) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDDa +OPCODE(0xD130) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDDa +OPCODE(0xD138) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(16) +} + +// ADDDa +OPCODE(0xD139) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(20) +} + +// ADDDa +OPCODE(0xD11F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD127) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, dst) + res = dst + src; + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ = res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(14) +} + +// ADDDa +OPCODE(0xD150) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD158) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD160) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ADDDa +OPCODE(0xD168) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDDa +OPCODE(0xD170) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDDa +OPCODE(0xD178) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ADDDa +OPCODE(0xD179) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ADDDa +OPCODE(0xD15F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ADDDa +OPCODE(0xD167) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 9) & 7); + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, dst) + res = dst + src; + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ = res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ADDDa +OPCODE(0xD190) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDDa +OPCODE(0xD198) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDDa +OPCODE(0xD1A0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ADDDa +OPCODE(0xD1A8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ADDDa +OPCODE(0xD1B0) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(26) +} + +// ADDDa +OPCODE(0xD1B8) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_SWORD(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(24) +} + +// ADDDa +OPCODE(0xD1B9) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + FETCH_LONG(adr); + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(28) +} + +// ADDDa +OPCODE(0xD19F) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(20) +} + +// ADDDa +OPCODE(0xD1A7) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 9) & 7); + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, dst) + res = dst + src; + flag_NotZ = res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(22) +} + +// ADDX +OPCODE(0xD100) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu8((Opcode >> 0) & 7); + dst = DREGu8((Opcode >> 9) & 7); + res = dst + src + ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ |= res & 0xFF; + DREGu8((Opcode >> 9) & 7) = res; +RET(4) +} + +// ADDX +OPCODE(0xD140) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu16((Opcode >> 0) & 7); + dst = DREGu16((Opcode >> 9) & 7); + res = dst + src + ((flag_X >> 8) & 1); + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + DREGu16((Opcode >> 9) & 7) = res; +RET(4) +} + +// ADDX +OPCODE(0xD180) +{ + u32 adr, res; + u32 src, dst; + + src = DREGu32((Opcode >> 0) & 7); + dst = DREGu32((Opcode >> 9) & 7); + res = dst + src + ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + DREGu32((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDXM +OPCODE(0xD108) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDXM +OPCODE(0xD148) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + READ_WORD_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDXM +OPCODE(0xD188) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + READ_LONG_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDX7M +OPCODE(0xD10F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 1; + AREG((Opcode >> 9) & 7) = adr; + READ_BYTE_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDX7M +OPCODE(0xD14F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 2; + AREG((Opcode >> 9) & 7) = adr; + READ_WORD_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDX7M +OPCODE(0xD18F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG((Opcode >> 9) & 7) - 4; + AREG((Opcode >> 9) & 7) = adr; + READ_LONG_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDXM7 +OPCODE(0xDF08) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 1; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDXM7 +OPCODE(0xDF48) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_WORD_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDXM7 +OPCODE(0xDF88) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7) - 4; + AREG(7) = adr; + READ_LONG_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDX7M7 +OPCODE(0xDF0F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_BYTE_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_BYTE_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_N = flag_X = flag_C = res; + flag_V = (src ^ res) & (dst ^ res); + flag_NotZ |= res & 0xFF; + WRITE_BYTE_F(adr, res) + POST_IO +RET(18) +} + +// ADDX7M7 +OPCODE(0xDF4F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + adr = AREG(7) - 2; + AREG(7) = adr; + READ_WORD_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_V = ((src ^ res) & (dst ^ res)) >> 8; + flag_N = flag_X = flag_C = res >> 8; + flag_NotZ |= res & 0xFFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ADDX7M7 +OPCODE(0xDF8F) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READ_LONG_F(adr, src) + adr = AREG(7) - 4; + AREG(7) = adr; + READ_LONG_F(adr, dst) + res = dst + src + ((flag_X >> 8) & 1); + flag_NotZ |= res; + flag_X = flag_C = ((src & dst & 1) + (src >> 1) + (dst >> 1)) >> 23; + flag_V = ((src ^ res) & (dst ^ res)) >> 24; + flag_N = res >> 24; + WRITE_LONG_F(adr, res) + POST_IO +RET(30) +} + +// ADDA +OPCODE(0xD0C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDA +OPCODE(0xD0C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs16((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +RET(8) +} + +// ADDA +OPCODE(0xD0D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// ADDA +OPCODE(0xD0D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// ADDA +OPCODE(0xD0E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(12) +#endif +} + +// ADDA +OPCODE(0xD0E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// ADDA +OPCODE(0xD0F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(16) +#endif +} + +// ADDA +OPCODE(0xD0F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// ADDA +OPCODE(0xD0F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(20) +#else +RET(18) +#endif +} + +// ADDA +OPCODE(0xD0FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// ADDA +OPCODE(0xD0FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(18) +#else +RET(16) +#endif +} + +// ADDA +OPCODE(0xD0FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +RET(12) +} + +// ADDA +OPCODE(0xD0DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(12) +#else +RET(10) +#endif +} + +// ADDA +OPCODE(0xD0E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READSX_WORD_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +#ifdef USE_CYCLONE_TIMING +RET(14) +#else +RET(12) +#endif +} + +// ADDA +OPCODE(0xD1C0) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)DREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(6) +#endif +} + +// ADDA +OPCODE(0xD1C8) +{ + u32 adr, res; + u32 src, dst; + + src = (s32)AREGs32((Opcode >> 0) & 7); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(8) +#else +RET(6) +#endif +} + +// ADDA +OPCODE(0xD1D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDA +OPCODE(0xD1D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDA +OPCODE(0xD1E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 4; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ADDA +OPCODE(0xD1E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDA +OPCODE(0xD1F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ADDA +OPCODE(0xD1F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDA +OPCODE(0xD1F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(22) +} + +// ADDA +OPCODE(0xD1FA) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_SWORD + GET_PC; + PC++; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(18) +} + +// ADDA +OPCODE(0xD1FB) +{ + u32 adr, res; + u32 src, dst; + + adr = GET_PC; + DECODE_EXT_WORD + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(20) +} + +// ADDA +OPCODE(0xD1FC) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(src); + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; +#ifdef USE_CYCLONE_TIMING +RET(16) +#else +RET(14) +#endif +} + +// ADDA +OPCODE(0xD1DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 4; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(14) +} + +// ADDA +OPCODE(0xD1E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 4; + AREG(7) = adr; + PRE_IO + READSX_LONG_F(adr, src) + dst = AREGu32((Opcode >> 9) & 7); + res = dst + src; + AREG((Opcode >> 9) & 7) = res; + POST_IO +RET(16) +} + +// ASRk +OPCODE(0xE000) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = (s32)DREGs8((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = ((s32)src) >> sft; + flag_N = res >> 0; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// ASRk +OPCODE(0xE040) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = (s32)DREGs16((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = ((s32)src) >> sft; + flag_N = res >> 8; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// ASRk +OPCODE(0xE080) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = (s32)DREGs32((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = ((s32)src) >> sft; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// LSRk +OPCODE(0xE008) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + flag_N = flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = src >> sft; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// LSRk +OPCODE(0xE048) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + flag_N = flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = src >> sft; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// LSRk +OPCODE(0xE088) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_N = flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = src >> sft; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ROXRk +OPCODE(0xE010) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + src |= (flag_X & M68K_SR_X) << 0; + res = (src >> sft) | (src << (9 - sft)); + flag_X = flag_C = res >> 0; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROXRk +OPCODE(0xE050) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + src |= (flag_X & M68K_SR_X) << 8; + res = (src >> sft) | (src << (17 - sft)); + flag_X = flag_C = res >> 8; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROXRk +OPCODE(0xE090) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + if (sft == 1) res = (src >> 1) | ((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + 1))); + else res = (src >> sft) | (src << (33 - sft)) | ((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + sft))); + flag_X = flag_C; + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// RORk +OPCODE(0xE018) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = (src >> sft) | (src << (8 - sft)); + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// RORk +OPCODE(0xE058) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = (src >> sft) | (src << (16 - sft)); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// RORk +OPCODE(0xE098) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = (src >> sft) | (src << (32 - sft)); + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ASLk +OPCODE(0xE100) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + if (sft < 8) + { + flag_X = flag_C = src << (0 + sft); + res = src << sft; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; + flag_V = 0; + if ((sft > 7) && (src)) flag_V = M68K_SR_V; + else + { + u32 msk = (((s32)0x80000000) >> (sft + 24)) & 0x000000FF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } + RET(6) + } + + if (src) flag_V = M68K_SR_V; + else flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + flag_N = 0; + flag_NotZ = 0; +RET(6) +} + +// ASLk +OPCODE(0xE140) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + flag_X = flag_C = src >> (8 - sft); + res = src << sft; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; + flag_V = 0; + { + u32 msk = (((s32)0x80000000) >> (sft + 16)) & 0x0000FFFF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } +RET(6) +} + +// ASLk +OPCODE(0xE180) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_X = flag_C = src >> (24 - sft); + res = src << sft; + flag_N = res >> 24; + flag_NotZ = res & 0xFFFFFFFF; + DREGu32((Opcode >> 0) & 7) = res; + flag_V = 0; + { + u32 msk = (((s32)0x80000000) >> (sft + 0)) & 0xFFFFFFFF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } +RET(8) +} + +// LSLk +OPCODE(0xE108) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src << (0 + sft); + res = src << sft; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// LSLk +OPCODE(0xE148) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src >> (8 - sft); + res = src << sft; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// LSLk +OPCODE(0xE188) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_V = 0; + flag_X = flag_C = src >> (24 - sft); + res = src << sft; + flag_N = res >> 24; + flag_NotZ = res & 0xFFFFFFFF; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ROXLk +OPCODE(0xE110) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + src |= (flag_X & M68K_SR_X) << 0; + res = (src << sft) | (src >> (9 - sft)); + flag_X = flag_C = res >> 0; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROXLk +OPCODE(0xE150) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + src |= (flag_X & M68K_SR_X) << 8; + res = (src << sft) | (src >> (17 - sft)); + flag_X = flag_C = res >> 8; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROXLk +OPCODE(0xE190) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_C = src >> ((32 - M68K_SR_C_SFT) - sft); + if (sft == 1) res = (src << 1) | ((flag_X & M68K_SR_X) >> ((M68K_SR_X_SFT + 1) - 1)); + else res = (src << sft) | (src >> (33 - sft)) | ((flag_X & M68K_SR_X) >> ((M68K_SR_X_SFT + 1) - sft)); + flag_X = flag_C; + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ROLk +OPCODE(0xE118) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu8((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src << (0 + sft); + res = (src << sft) | (src >> (8 - sft)); + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROLk +OPCODE(0xE158) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu16((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src >> (8 - sft); + res = (src << sft) | (src >> (16 - sft)); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; +RET(6) +} + +// ROLk +OPCODE(0xE198) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = (((Opcode >> 9) - 1) & 7) + 1; + m68kcontext.io_cycle_counter -= sft * 2; + src = DREGu32((Opcode >> 0) & 7); + flag_V = 0; + flag_C = src >> (24 - sft); + res = (src << sft) | (src >> (32 - sft)); + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; +RET(8) +} + +// ASRD +OPCODE(0xE020) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = (s32)DREGs8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 8) + { + flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = ((s32)src) >> sft; + flag_N = res >> 0; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + if (src & (1 << 7)) + { + flag_N = M68K_SR_N; + flag_NotZ = 1; + flag_V = 0; + flag_C = M68K_SR_C; + flag_X = M68K_SR_X; + res = 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + flag_C = 0; + flag_X = 0; + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// ASRD +OPCODE(0xE060) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = (s32)DREGs16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 16) + { + flag_V = 0; + flag_X = flag_C = (src >> (sft - 1)) << M68K_SR_C_SFT; + res = ((s32)src) >> sft; + flag_N = res >> 8; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + if (src & (1 << 15)) + { + flag_N = M68K_SR_N; + flag_NotZ = 1; + flag_V = 0; + flag_C = M68K_SR_C; + flag_X = M68K_SR_X; + res = 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + flag_C = 0; + flag_X = 0; + res = 0; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// ASRD +OPCODE(0xE0A0) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = (s32)DREGs32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 32) + { + flag_V = 0; + flag_X = flag_C = (src >> (sft - 1)) << M68K_SR_C_SFT; + res = ((s32)src) >> sft; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + if (src & (1 << 31)) + { + flag_N = M68K_SR_N; + flag_NotZ = 1; + flag_V = 0; + flag_C = M68K_SR_C; + flag_X = M68K_SR_X; + res = 0xFFFFFFFF; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + flag_C = 0; + flag_X = 0; + res = 0; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// LSRD +OPCODE(0xE028) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft <= 8) + { + flag_N = flag_V = 0; + flag_X = flag_C = src << ((M68K_SR_C_SFT + 1) - sft); + res = src >> sft; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_X = flag_C = 0; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// LSRD +OPCODE(0xE068) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft <= 16) + { + flag_N = flag_V = 0; + flag_X = flag_C = (src >> (sft - 1)) << M68K_SR_C_SFT; + res = src >> sft; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_X = flag_C = 0; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// LSRD +OPCODE(0xE0A8) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 32) + { + flag_N = flag_V = 0; + flag_X = flag_C = (src >> (sft - 1)) << M68K_SR_C_SFT; + res = src >> sft; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + if (sft == 32) flag_C = src >> (31 - M68K_SR_C_SFT); + else flag_C = 0; + flag_X = flag_C; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// ROXRD +OPCODE(0xE030) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 9; + + src |= (flag_X & M68K_SR_X) << 0; + res = (src >> sft) | (src << (9 - sft)); + flag_X = flag_C = res >> 0; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// ROXRD +OPCODE(0xE070) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 17; + + src |= (flag_X & M68K_SR_X) << 8; + res = (src >> sft) | (src << (17 - sft)); + flag_X = flag_C = res >> 8; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// ROXRD +OPCODE(0xE0B0) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 33; + + if (sft != 0) + { + if (sft == 1) res = (src >> 1) | ((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + 1))); + else res = (src >> sft) | (src << (33 - sft)) | (((flag_X & M68K_SR_X) << (32 - (M68K_SR_X_SFT + 1))) >> (sft - 1)); + flag_X = (src >> (32 - sft)) << M68K_SR_X_SFT; + } + else res = src; + flag_C = flag_X; + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// RORD +OPCODE(0xE038) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft &= 0x07; + + flag_C = src << (M68K_SR_C_SFT - ((sft - 1) & 7)); + res = (src >> sft) | (src << (8 - sft)); + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// RORD +OPCODE(0xE078) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft &= 0x0F; + + flag_C = (src >> ((sft - 1) & 15)) << M68K_SR_C_SFT; + res = (src >> sft) | (src << (16 - sft)); + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// RORD +OPCODE(0xE0B8) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft &= 0x1F; + + flag_C = (src >> ((sft - 1) & 31)) << M68K_SR_C_SFT; + res = (src >> sft) | (src << (32 - sft)); + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// ASLD +OPCODE(0xE120) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 8) + { + flag_X = flag_C = (src << sft) >> 0; + res = (src << sft) & 0x000000FF; + flag_N = res >> 0; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; + flag_V = 0; + { + u32 msk = (((s32)0x80000000) >> (sft + 24)) & 0x000000FF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } + RET(6) + } + + if (sft == 256) flag_C = src << M68K_SR_C_SFT; + else flag_C = 0; + flag_X = flag_C; + if (src) flag_V = M68K_SR_V; + else flag_V = 0; + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + flag_N = 0; + flag_NotZ = 0; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// ASLD +OPCODE(0xE160) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 16) + { + flag_X = flag_C = (src << sft) >> 8; + res = (src << sft) & 0x0000FFFF; + flag_N = res >> 8; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; + flag_V = 0; + { + u32 msk = (((s32)0x80000000) >> (sft + 16)) & 0x0000FFFF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } + RET(6) + } + + if (sft == 65536) flag_C = src << M68K_SR_C_SFT; + else flag_C = 0; + flag_X = flag_C; + if (src) flag_V = M68K_SR_V; + else flag_V = 0; + res = 0; + DREGu16((Opcode >> 0) & 7) = res; + flag_N = 0; + flag_NotZ = 0; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// ASLD +OPCODE(0xE1A0) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 32) + { + flag_X = flag_C = (src >> (32 - sft)) << M68K_SR_C_SFT; + res = src << sft; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + flag_V = 0; + { + u32 msk = (((s32)0x80000000) >> (sft + 0)) & 0xFFFFFFFF; + src &= msk; + if ((src) && (src != msk)) flag_V = M68K_SR_V; + } + RET(CYC) + } + + if (sft == 0) flag_C = src << M68K_SR_C_SFT; + else flag_C = 0; + flag_X = flag_C; + if (src) flag_V = M68K_SR_V; + else flag_V = 0; + res = 0; + DREGu32((Opcode >> 0) & 7) = res; + flag_N = 0; + flag_NotZ = 0; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// LSLD +OPCODE(0xE128) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft <= 8) + { + flag_X = flag_C = (src << sft) >> 0; + res = (src << sft) & 0x000000FF; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_X = flag_C = 0; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// LSLD +OPCODE(0xE168) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft <= 16) + { + flag_X = flag_C = (src << sft) >> 8; + res = (src << sft) & 0x0000FFFF; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_X = flag_C = 0; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// LSLD +OPCODE(0xE1A8) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft < 32) + { + flag_X = flag_C = (src >> (32 - sft)) << M68K_SR_C_SFT; + res = src << sft; + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + if (sft == 32) flag_C = src << M68K_SR_C_SFT; + else flag_C = 0; + flag_X = flag_C; + flag_N = 0; + flag_NotZ = 0; + flag_V = 0; + res = 0; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// ROXLD +OPCODE(0xE130) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 9; + + src |= (flag_X & M68K_SR_X) << 0; + res = (src << sft) | (src >> (9 - sft)); + flag_X = flag_C = res >> 0; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res & 0x000000FF; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// ROXLD +OPCODE(0xE170) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 17; + + src |= (flag_X & M68K_SR_X) << 8; + res = (src << sft) | (src >> (17 - sft)); + flag_X = flag_C = res >> 8; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// ROXLD +OPCODE(0xE1B0) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + sft %= 33; + + if (sft != 0) + { + if (sft == 1) res = (src << 1) | ((flag_X >> ((M68K_SR_X_SFT + 1) - 1)) & 1); + else res = (src << sft) | (src >> (33 - sft)) | (((flag_X >> ((M68K_SR_X_SFT + 1) - 1)) & 1) << (sft - 1)); + flag_X = (src >> (32 - sft)) << M68K_SR_X_SFT; + } + else res = src; + flag_C = flag_X; + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = flag_X; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// ROLD +OPCODE(0xE138) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu8((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft &= 0x07) + { + flag_C = (src << sft) >> 0; + res = ((src << sft) | (src >> (8 - sft))) & 0x000000FF; + flag_V = 0; + flag_N = res >> 0; + flag_NotZ = res; + DREGu8((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + flag_N = src >> 0; + flag_NotZ = src; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 0; + flag_NotZ = src; +RET(6) +} + +// ROLD +OPCODE(0xE178) +{ + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu16((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft &= 0x0F) + { + flag_C = (src << sft) >> 8; + res = ((src << sft) | (src >> (16 - sft))) & 0x0000FFFF; + flag_V = 0; + flag_N = res >> 8; + flag_NotZ = res; + DREGu16((Opcode >> 0) & 7) = res; + RET(6) + } + + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + flag_N = src >> 8; + flag_NotZ = src; + RET(6) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 8; + flag_NotZ = src; +RET(6) +} + +// ROLD +OPCODE(0xE1B8) +{ +#ifdef USE_CYCLONE_TIMING +#define CYC 8 +#else +#define CYC 6 +#endif + u32 adr, res; + u32 src, dst; + + u32 sft; + + sft = DREG((Opcode >> 9) & 7) & 0x3F; + src = DREGu32((Opcode >> 0) & 7); + if (sft) + { + m68kcontext.io_cycle_counter -= sft * 2; + if (sft &= 0x1F) + { + flag_C = (src >> (32 - sft)) << M68K_SR_C_SFT; + res = (src << sft) | (src >> (32 - sft)); + flag_V = 0; + flag_N = res >> 24; + flag_NotZ = res; + DREGu32((Opcode >> 0) & 7) = res; + RET(CYC) + } + + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + flag_N = src >> 24; + flag_NotZ = src; + RET(CYC) + } + + flag_V = 0; + flag_C = 0; + flag_N = src >> 24; + flag_NotZ = src; +RET(CYC) +#undef CYC +} + +// ASR +OPCODE(0xE0D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASR +OPCODE(0xE0D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASR +OPCODE(0xE0E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ASR +OPCODE(0xE0E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ASR +OPCODE(0xE0F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ASR +OPCODE(0xE0F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ASR +OPCODE(0xE0F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ASR +OPCODE(0xE0DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASR +OPCODE(0xE0E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src & (1 << 15)); + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// LSR +OPCODE(0xE2D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSR +OPCODE(0xE2D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSR +OPCODE(0xE2E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// LSR +OPCODE(0xE2E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// LSR +OPCODE(0xE2F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// LSR +OPCODE(0xE2F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// LSR +OPCODE(0xE2F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// LSR +OPCODE(0xE2DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSR +OPCODE(0xE2E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_N = flag_V = 0; + flag_X = flag_C = src << M68K_SR_C_SFT; + res = src >> 1; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROXR +OPCODE(0xE4D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXR +OPCODE(0xE4D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXR +OPCODE(0xE4E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROXR +OPCODE(0xE4E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROXR +OPCODE(0xE4F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ROXR +OPCODE(0xE4F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROXR +OPCODE(0xE4F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ROXR +OPCODE(0xE4DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXR +OPCODE(0xE4E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src >> 1) | ((flag_X & M68K_SR_X) << 7); + flag_C = flag_X = src << M68K_SR_C_SFT; + flag_N = res >> 8; + flag_NotZ = res; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROR +OPCODE(0xE6D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROR +OPCODE(0xE6D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROR +OPCODE(0xE6E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROR +OPCODE(0xE6E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROR +OPCODE(0xE6F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ROR +OPCODE(0xE6F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROR +OPCODE(0xE6F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ROR +OPCODE(0xE6DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROR +OPCODE(0xE6E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src << M68K_SR_C_SFT; + res = (src >> 1) | (src << 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ASL +OPCODE(0xE1D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASL +OPCODE(0xE1D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASL +OPCODE(0xE1E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ASL +OPCODE(0xE1E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ASL +OPCODE(0xE1F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ASL +OPCODE(0xE1F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ASL +OPCODE(0xE1F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ASL +OPCODE(0xE1DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ASL +OPCODE(0xE1E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_X = flag_C = src >> 7; + res = src << 1; + flag_V = (src ^ res) >> 8; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// LSL +OPCODE(0xE3D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSL +OPCODE(0xE3D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSL +OPCODE(0xE3E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// LSL +OPCODE(0xE3E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// LSL +OPCODE(0xE3F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// LSL +OPCODE(0xE3F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// LSL +OPCODE(0xE3F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// LSL +OPCODE(0xE3DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// LSL +OPCODE(0xE3E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_X = flag_C = src >> 7; + res = src << 1; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROXL +OPCODE(0xE5D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXL +OPCODE(0xE5D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXL +OPCODE(0xE5E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROXL +OPCODE(0xE5E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROXL +OPCODE(0xE5F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ROXL +OPCODE(0xE5F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROXL +OPCODE(0xE5F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ROXL +OPCODE(0xE5DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROXL +OPCODE(0xE5E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + res = (src << 1) | ((flag_X & M68K_SR_X) >> 8); + flag_X = flag_C = src >> 7; + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROL +OPCODE(0xE7D0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROL +OPCODE(0xE7D8) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + AREG((Opcode >> 0) & 7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROL +OPCODE(0xE7E0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7) - 2; + AREG((Opcode >> 0) & 7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +// ROL +OPCODE(0xE7E8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + adr += AREG((Opcode >> 0) & 7); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROL +OPCODE(0xE7F0) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG((Opcode >> 0) & 7); + DECODE_EXT_WORD + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(18) +} + +// ROL +OPCODE(0xE7F8) +{ + u32 adr, res; + u32 src, dst; + + FETCH_SWORD(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(16) +} + +// ROL +OPCODE(0xE7F9) +{ + u32 adr, res; + u32 src, dst; + + FETCH_LONG(adr); + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(20) +} + +// ROL +OPCODE(0xE7DF) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7); + AREG(7) += 2; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(12) +} + +// ROL +OPCODE(0xE7E7) +{ + u32 adr, res; + u32 src, dst; + + adr = AREG(7) - 2; + AREG(7) = adr; + PRE_IO + READ_WORD_F(adr, src) + flag_V = 0; + flag_C = src >> 7; + res = (src << 1) | (src >> 15); + flag_N = res >> 8; + flag_NotZ = res & 0x0000FFFF; + WRITE_WORD_F(adr, res) + POST_IO +RET(14) +} + +#ifdef PICODRIVE_HACK +#if 0 +#define UPDATE_IDLE_COUNT { \ + extern int idle_hit_counter; \ + idle_hit_counter++; \ +} +#else +#define UPDATE_IDLE_COUNT +#endif + +// BRA +OPCODE(0x6001_idle) +{ +#ifdef FAMEC_CHECK_BRANCHES + u32 newPC = GET_PC; + s8 offs=Opcode; + newPC += offs; + SET_PC(newPC); + CHECK_BRANCH_EXCEPTION(offs) +#else + PC += ((s8)(Opcode & 0xFE)) >> 1; +#endif + UPDATE_IDLE_COUNT +RET0() +} + +// BCC +OPCODE(0x6601_idle) +{ + if (flag_NotZ) + { + UPDATE_IDLE_COUNT + PC += ((s8)(Opcode & 0xFE)) >> 1; + //if (idle_hit) + RET0() + } +RET(8) +} + +OPCODE(0x6701_idle) +{ + if (!flag_NotZ) + { + UPDATE_IDLE_COUNT + PC += ((s8)(Opcode & 0xFE)) >> 1; + //if (idle_hit) + RET0() + } +RET(8) +} + + +extern int SekIsIdleReady(void); +extern int SekIsIdleCode(unsigned short *dst, int bytes); +extern int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx); + +OPCODE(idle_detector_bcc8) +{ + int frame_count, cond_true, bytes, ret, newop; + u16 *dest_pc; + + dest_pc = PC + (((s8)(Opcode & 0xFE)) >> 1); + + if (!SekIsIdleReady()) + goto end; + + bytes = 0 - (s8)(Opcode & 0xFE) - 2; + ret = SekIsIdleCode(dest_pc, bytes); + newop = (Opcode & 0xfe) | 0x7100; + if (!ret) newop |= 0x200; + if ( Opcode & 0x0100) newop |= 0x400; // beq + if (!(Opcode & 0x0f00)) newop |= 0xc00; // bra + + ret = SekRegisterIdlePatch(GET_PC - 2, Opcode, newop, &m68kcontext); + switch (ret) + { + case 0: PC[-1] = newop; break; + case 1: break; + case 2: JumpTable[Opcode] = (Opcode & 0x0f00) ? + ((Opcode & 0x0100) ? CAST_OP(0x6701) : CAST_OP(0x6601)) : + CAST_OP(0x6001); break; + } + +end: + if ((Opcode & 0xff00) == 0x6000) cond_true = 1; + else cond_true = (Opcode & 0x0100) ? !flag_NotZ : flag_NotZ; // beq? + if (cond_true) + { + PC = dest_pc; + m68kcontext.io_cycle_counter -= 2; + } +RET(8) +} + +#endif // PICODRIVE_HACK diff --git a/waterbox/picodrive/cpu/sh2/mame/sh2.inc b/waterbox/picodrive/cpu/sh2/mame/sh2.inc new file mode 100644 index 0000000000..81203e7b46 --- /dev/null +++ b/waterbox/picodrive/cpu/sh2/mame/sh2.inc @@ -0,0 +1,2173 @@ +/***************************************************************************** + * + * sh2.c + * Portable Hitachi SH-2 (SH7600 family) emulator + * + * Copyright Juergen Buchmueller , + * all rights reserved. + * + * - This source code is released as freeware for non-commercial purposes. + * - You are free to use and redistribute this code in modified or + * unmodified form, provided you list me in the credits. + * - If you modify this source code, you must add a notice to each modified + * source file that it has been changed. If you're a nice person, you + * will clearly mark each change too. :) + * - If you wish to use this for commercial purposes, please contact me at + * pullmoll@t-online.de + * - The author of this copywritten work reserves the right to change the + * terms of its usage and license at any time, including retroactively + * - This entire notice must remain in the source code. + * + * This work is based on C/C++ implementation of + * the SH-2 CPU core and was adapted to the MAME CPU core requirements. + * Thanks also go to Chuck Mason and Olivier Galibert + * for letting me peek into their SEMU code :-) + * + *****************************************************************************/ + +/***************************************************************************** + Changes + 20130129 Angelo Salese + - added illegal opcode exception handling, side effect of some Saturn games + on loading like Feda or Falcom Classics Vol. 1 + (i.e. Master CPU Incautiously transfers memory from CD to work RAM H, and + wipes out Slave CPU program code too while at it). + + 20051129 Mariusz Wojcieszek + - introduced memory_decrypted_read_word() for opcode fetching + + 20050813 Mariusz Wojcieszek + - fixed 64 bit / 32 bit division in division unit + + 20031015 O. Galibert + - dma fixes, thanks to sthief + + 20031013 O. Galibert, A. Giles + - timer fixes + - multi-cpu simplifications + + 20030915 O. Galibert + - fix DMA1 irq vector + - ignore writes to DRCRx + - fix cpu number issues + - fix slave/master recognition + - fix wrong-cpu-in-context problem with the timers + + 20021020 O. Galibert + - DMA implementation, lightly tested + - delay slot in debugger fixed + - add divide box mirrors + - Nicola-ify the indentation + - Uncrapify sh2_internal_* + - Put back nmi support that had been lost somehow + + 20020914 R. Belmont + - Initial SH2 internal timers implementation, based on code by O. Galibert. + Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games. + - Fix to external division, thanks to "spice" on the E2J board. + Corrects behavior of s1945ii turret boss. + + 20020302 Olivier Galibert (galibert@mame.net) + - Fixed interrupt in delay slot + - Fixed rotcr + - Fixed div1 + - Fixed mulu + - Fixed negc + + 20020301 R. Belmont + - Fixed external division + + 20020225 Olivier Galibert (galibert@mame.net) + - Fixed interrupt handling + + 20010207 Sylvain Glaize (mokona@puupuu.org) + + - Bug fix in INLINE void MOVBM(UINT32 m, UINT32 n) (see comment) + - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions) + reason : when the two high bits of the address are set, access is + done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM + sets the stack pointer here, using these addresses as usual RAM access. + + No real cache support has been added. + - Read/Write memory format correction (_bew to _bedw) (see also SH2 + definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c ) + + 20010623 James Forshaw (TyRaNiD@totalise.net) + + - Modified operation of sh2_exception. Done cause mame irq system is stupid, and + doesnt really seem designed for any more than 8 interrupt lines. + + 20010701 James Forshaw (TyRaNiD@totalise.net) + + - Fixed DIV1 operation. Q bit now correctly generated + + 20020218 Added save states (mokona@puupuu.org) + + *****************************************************************************/ + +//#include "debugger.h" +//#include "sh2.h" +//#include "sh2comn.h" +#define INLINE static + +//CPU_DISASSEMBLE( sh2 ); + +#ifndef USE_SH2DRC + +/* speed up delay loops, bail out of tight loops */ +//#define BUSY_LOOP_HACKS 1 + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +#if 0 +INLINE UINT8 RB(sh2_state *sh2, offs_t A) +{ + if (A >= 0xe0000000) + return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xff << (((~A) & 3)*8)) >> (((~A) & 3)*8); + + if (A >= 0xc0000000) + return sh2->program->read_byte(A); + + if (A >= 0x40000000) + return 0xa5; + + return sh2->program->read_byte(A & AM); +} + +INLINE UINT16 RW(sh2_state *sh2, offs_t A) +{ + if (A >= 0xe0000000) + return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffff << (((~A) & 2)*8)) >> (((~A) & 2)*8); + + if (A >= 0xc0000000) + return sh2->program->read_word(A); + + if (A >= 0x40000000) + return 0xa5a5; + + return sh2->program->read_word(A & AM); +} + +INLINE UINT32 RL(sh2_state *sh2, offs_t A) +{ + if (A >= 0xe0000000) + return sh2_internal_r(*sh2->internal, (A & 0x1fc)>>2, 0xffffffff); + + if (A >= 0xc0000000) + return sh2->program->read_dword(A); + + if (A >= 0x40000000) + return 0xa5a5a5a5; + + return sh2->program->read_dword(A & AM); +} + +INLINE void WB(sh2_state *sh2, offs_t A, UINT8 V) +{ + if (A >= 0xe0000000) + { + sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 3)*8), 0xff << (((~A) & 3)*8)); + return; + } + + if (A >= 0xc0000000) + { + sh2->program->write_byte(A,V); + return; + } + + if (A >= 0x40000000) + return; + + sh2->program->write_byte(A & AM,V); +} + +INLINE void WW(sh2_state *sh2, offs_t A, UINT16 V) +{ + if (A >= 0xe0000000) + { + sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V << (((~A) & 2)*8), 0xffff << (((~A) & 2)*8)); + return; + } + + if (A >= 0xc0000000) + { + sh2->program->write_word(A,V); + return; + } + + if (A >= 0x40000000) + return; + + sh2->program->write_word(A & AM,V); +} + +INLINE void WL(sh2_state *sh2, offs_t A, UINT32 V) +{ + if (A >= 0xe0000000) + { + sh2_internal_w(*sh2->internal, (A & 0x1fc)>>2, V, 0xffffffff); + return; + } + + if (A >= 0xc0000000) + { + sh2->program->write_dword(A,V); + return; + } + + if (A >= 0x40000000) + return; + + sh2->program->write_dword(A & AM,V); +} +#endif + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +INLINE void ADD(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] += sh2->r[m]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +INLINE void ADDI(sh2_state *sh2, UINT32 i, UINT32 n) +{ + sh2->r[n] += (INT32)(INT16)(INT8)i; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +INLINE void ADDC(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 tmp0, tmp1; + + tmp1 = sh2->r[n] + sh2->r[m]; + tmp0 = sh2->r[n]; + sh2->r[n] = tmp1 + (sh2->sr & T); + if (tmp0 > tmp1) + sh2->sr |= T; + else + sh2->sr &= ~T; + if (tmp1 > sh2->r[n]) + sh2->sr |= T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1111 1 overflow + * ADDV Rm,Rn + */ +INLINE void ADDV(sh2_state *sh2, UINT32 m, UINT32 n) +{ + INT32 dest, src, ans; + + if ((INT32) sh2->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((INT32) sh2->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + sh2->r[n] += sh2->r[m]; + if ((INT32) sh2->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + sh2->sr |= T; + else + sh2->sr &= ~T; + } + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1001 1 - + * AND Rm,Rn + */ +INLINE void AND(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] &= sh2->r[m]; +} + + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +INLINE void ANDI(sh2_state *sh2, UINT32 i) +{ + sh2->r[0] &= i; +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +INLINE void ANDM(sh2_state *sh2, UINT32 i) +{ + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = i & RB( sh2, sh2->ea ); + WB( sh2, sh2->ea, temp ); + sh2->icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +INLINE void BF(sh2_state *sh2, UINT32 d) +{ + if ((sh2->sr & T) == 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +INLINE void BFS(sh2_state *sh2, UINT32 d) +{ + sh2->delay = sh2->pc; + sh2->pc += 2; + + if ((sh2->sr & T) == 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2; + sh2->icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +INLINE void BRA(sh2_state *sh2, UINT32 d) +{ + INT32 disp = ((INT32)d << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + UINT32 next_opcode = RW( sh2, sh2->ppc & AM ); + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009) + sh2->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + } +#endif + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +INLINE void BRAF(sh2_state *sh2, UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pc += sh2->r[m] + 2; + sh2->icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +INLINE void BSR(sh2_state *sh2, UINT32 d) +{ + INT32 disp = ((INT32)d << 20) >> 20; + + sh2->pr = sh2->pc + 2; + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +INLINE void BSRF(sh2_state *sh2, UINT32 m) +{ + sh2->pr = sh2->pc + 2; + sh2->delay = sh2->pc; + sh2->pc += sh2->r[m] + 2; + sh2->icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +INLINE void BT(sh2_state *sh2, UINT32 d) +{ + if ((sh2->sr & T) != 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2 + 2; + sh2->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +INLINE void BTS(sh2_state *sh2, UINT32 d) +{ + sh2->delay = sh2->pc; + sh2->pc += 2; + + if ((sh2->sr & T) != 0) + { + INT32 disp = ((INT32)d << 24) >> 24; + sh2->pc = sh2->ea = sh2->pc + disp * 2; + sh2->icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +INLINE void CLRMAC(sh2_state *sh2) +{ + sh2->mach = 0; + sh2->macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +INLINE void CLRT(sh2_state *sh2) +{ + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +INLINE void CMPEQ(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if (sh2->r[n] == sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +INLINE void CMPGE(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((INT32) sh2->r[n] >= (INT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +INLINE void CMPGT(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((INT32) sh2->r[n] > (INT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +INLINE void CMPHI(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((UINT32) sh2->r[n] > (UINT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +INLINE void CMPHS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((UINT32) sh2->r[n] >= (UINT32) sh2->r[m]) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +INLINE void CMPPL(sh2_state *sh2, UINT32 n) +{ + if ((INT32) sh2->r[n] > 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +INLINE void CMPPZ(sh2_state *sh2, UINT32 n) +{ + if ((INT32) sh2->r[n] >= 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +INLINE void CMPSTR(sh2_state *sh2, UINT32 m, UINT32 n) + { + UINT32 temp; + INT32 HH, HL, LH, LL; + temp = sh2->r[n] ^ sh2->r[m]; + HH = (temp >> 24) & 0xff; + HL = (temp >> 16) & 0xff; + LH = (temp >> 8) & 0xff; + LL = temp & 0xff; + if (HH && HL && LH && LL) + sh2->sr &= ~T; + else + sh2->sr |= T; + } + + +/* code cycles t-bit + * 1000 1000 iiii iiii 1 comparison result + * CMP/EQ #imm,R0 + */ +INLINE void CMPIM(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i; + + if (sh2->r[0] == imm) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 0111 1 calculation result + * DIV0S Rm,Rn + */ +INLINE void DIV0S(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((sh2->r[n] & 0x80000000) == 0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + if ((sh2->r[m] & 0x80000000) == 0) + sh2->sr &= ~M; + else + sh2->sr |= M; + if ((sh2->r[m] ^ sh2->r[n]) & 0x80000000) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* code cycles t-bit + * 0000 0000 0001 1001 1 0 + * DIV0U + */ +INLINE void DIV0U(sh2_state *sh2) +{ + sh2->sr &= ~(M | Q | T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +INLINE void DIV1(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 tmp0; + UINT32 old_q; + + old_q = sh2->sr & Q; + if (0x80000000 & sh2->r[n]) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + + sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); + + if (!old_q) + { + if (!(sh2->sr & M)) + { + tmp0 = sh2->r[n]; + sh2->r[n] -= sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] > tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + else + if(sh2->r[n] > tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + tmp0 = sh2->r[n]; + sh2->r[n] += sh2->r[m]; + if(!(sh2->sr & Q)) + { + if(sh2->r[n] < tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + if(sh2->r[n] < tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + } + } + } + else + { + if (!(sh2->sr & M)) + { + tmp0 = sh2->r[n]; + sh2->r[n] += sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] < tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + else + if(sh2->r[n] < tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + } + else + { + tmp0 = sh2->r[n]; + sh2->r[n] -= sh2->r[m]; + if(!(sh2->sr & Q)) + if(sh2->r[n] > tmp0) + sh2->sr &= ~Q; + else + sh2->sr |= Q; + else + if(sh2->r[n] > tmp0) + sh2->sr |= Q; + else + sh2->sr &= ~Q; + } + } + + tmp0 = (sh2->sr & (Q | M)); + if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* DMULS.L Rm,Rn */ +INLINE void DMULS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) sh2->r[n]; + tempm = (INT32) sh2->r[m]; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + if ((INT32) (sh2->r[n] ^ sh2->r[m]) < 0) + fnLmL = -1; + else + fnLmL = 0; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + sh2->mach = Res2; + sh2->macl = Res0; + sh2->icount--; +} + +/* DMULU.L Rm,Rn */ +INLINE void DMULU(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + + RnL = sh2->r[n] & 0x0000ffff; + RnH = (sh2->r[n] >> 16) & 0x0000ffff; + RmL = sh2->r[m] & 0x0000ffff; + RmH = (sh2->r[m] >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + sh2->mach = Res2; + sh2->macl = Res0; + sh2->icount--; +} + +/* DT Rn */ +INLINE void DT(sh2_state *sh2, UINT32 n) +{ + sh2->r[n]--; + if (sh2->r[n] == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +#if BUSY_LOOP_HACKS + { + UINT32 next_opcode = RW( sh2, sh2->ppc & AM ); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + while (sh2->r[n] > 1 && sh2->icount > 4) + { + sh2->r[n]--; + sh2->icount -= 4; /* cycles for DT (1) and BF taken (3) */ + } + } + } +#endif +} + +/* EXTS.B Rm,Rn */ +INLINE void EXTSB(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = ((INT32)sh2->r[m] << 24) >> 24; +} + +/* EXTS.W Rm,Rn */ +INLINE void EXTSW(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = ((INT32)sh2->r[m] << 16) >> 16; +} + +/* EXTU.B Rm,Rn */ +INLINE void EXTUB(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +INLINE void EXTUW(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m] & 0x0000ffff; +} + +/* ILLEGAL */ +INLINE void ILLEGAL(sh2_state *sh2) +{ + logerror("SH2: Illegal opcode at %08x\n", sh2->pc - 2); + sh2->r[15] -= 4; + WL( sh2, sh2->r[15], sh2->sr ); /* push SR onto stack */ + sh2->r[15] -= 4; + WL( sh2, sh2->r[15], sh2->pc - 2 ); /* push PC onto stack */ + + /* fetch PC */ + sh2->pc = RL( sh2, sh2->vbr + 4 * 4 ); + + /* TODO: timing is a guess */ + sh2->icount -= 5; +} + + +/* JMP @Rm */ +INLINE void JMP(sh2_state *sh2, UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->r[m]; + sh2->icount--; +} + +/* JSR @Rm */ +INLINE void JSR(sh2_state *sh2, UINT32 m) +{ + sh2->delay = sh2->pc; + sh2->pr = sh2->pc + 2; + sh2->pc = sh2->ea = sh2->r[m]; + sh2->icount--; +} + + +/* LDC Rm,SR */ +INLINE void LDCSR(sh2_state *sh2, UINT32 m) +{ + sh2->sr = sh2->r[m] & FLAGS; + sh2->test_irq = 1; +} + +/* LDC Rm,GBR */ +INLINE void LDCGBR(sh2_state *sh2, UINT32 m) +{ + sh2->gbr = sh2->r[m]; +} + +/* LDC Rm,VBR */ +INLINE void LDCVBR(sh2_state *sh2, UINT32 m) +{ + sh2->vbr = sh2->r[m]; +} + +/* LDC.L @Rm+,SR */ +INLINE void LDCMSR(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->sr = RL( sh2, sh2->ea ) & FLAGS; + sh2->r[m] += 4; + sh2->icount -= 2; + sh2->test_irq = 1; +} + +/* LDC.L @Rm+,GBR */ +INLINE void LDCMGBR(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->gbr = RL( sh2, sh2->ea ); + sh2->r[m] += 4; + sh2->icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +INLINE void LDCMVBR(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->vbr = RL( sh2, sh2->ea ); + sh2->r[m] += 4; + sh2->icount -= 2; +} + +/* LDS Rm,MACH */ +INLINE void LDSMACH(sh2_state *sh2, UINT32 m) +{ + sh2->mach = sh2->r[m]; +} + +/* LDS Rm,MACL */ +INLINE void LDSMACL(sh2_state *sh2, UINT32 m) +{ + sh2->macl = sh2->r[m]; +} + +/* LDS Rm,PR */ +INLINE void LDSPR(sh2_state *sh2, UINT32 m) +{ + sh2->pr = sh2->r[m]; +} + +/* LDS.L @Rm+,MACH */ +INLINE void LDSMMACH(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->mach = RL( sh2, sh2->ea ); + sh2->r[m] += 4; +} + +/* LDS.L @Rm+,MACL */ +INLINE void LDSMMACL(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->macl = RL( sh2, sh2->ea ); + sh2->r[m] += 4; +} + +/* LDS.L @Rm+,PR */ +INLINE void LDSMPR(sh2_state *sh2, UINT32 m) +{ + sh2->ea = sh2->r[m]; + sh2->pr = RL( sh2, sh2->ea ); + sh2->r[m] += 4; +} + +/* MAC.L @Rm+,@Rn+ */ +INLINE void MAC_L(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) RL( sh2, sh2->r[n] ); + sh2->r[n] += 4; + tempm = (INT32) RL( sh2, sh2->r[m] ); + sh2->r[m] += 4; + if ((INT32) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (sh2->sr & S) + { + Res0 = sh2->macl + Res0; + if (sh2->macl > Res0) + Res2++; + Res2 += (sh2->mach & 0x0000ffff); + if (((INT32) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + sh2->mach = Res2; + sh2->macl = Res0; + } + else + { + Res0 = sh2->macl + Res0; + if (sh2->macl > Res0) + Res2++; + Res2 += sh2->mach; + sh2->mach = Res2; + sh2->macl = Res0; + } + sh2->icount -= 2; +} + +/* MAC.W @Rm+,@Rn+ */ +INLINE void MAC_W(sh2_state *sh2, UINT32 m, UINT32 n) +{ + INT32 tempm, tempn, dest, src, ans; + UINT32 templ; + + tempn = (INT32) RW( sh2, sh2->r[n] ); + sh2->r[n] += 2; + tempm = (INT32) RW( sh2, sh2->r[m] ); + sh2->r[m] += 2; + templ = sh2->macl; + tempm = ((INT32) (short) tempn * (INT32) (short) tempm); + if ((INT32) sh2->macl >= 0) + dest = 0; + else + dest = 1; + if ((INT32) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + sh2->macl += tempm; + if ((INT32) sh2->macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (sh2->sr & S) + { + if (ans == 1) + { + if (src == 0) + sh2->macl = 0x7fffffff; + if (src == 2) + sh2->macl = 0x80000000; + } + } + else + { + sh2->mach += tempn; + if (templ > sh2->macl) + sh2->mach += 1; + } + sh2->icount -= 2; +} + +/* MOV Rm,Rn */ +INLINE void MOV(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = sh2->r[m]; +} + +/* MOV.B Rm,@Rn */ +INLINE void MOVBS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff); +} + +/* MOV.W Rm,@Rn */ +INLINE void MOVWS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff); +} + +/* MOV.L Rm,@Rn */ +INLINE void MOVLS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->r[m] ); +} + +/* MOV.B @Rm,Rn */ +INLINE void MOVBL(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); +} + +/* MOV.W @Rm,Rn */ +INLINE void MOVWL(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); +} + +/* MOV.L @Rm,Rn */ +INLINE void MOVLL(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m]; + sh2->r[n] = RL( sh2, sh2->ea ); +} + +/* MOV.B Rm,@-Rn */ +INLINE void MOVBM(sh2_state *sh2, UINT32 m, UINT32 n) +{ + /* SMG : bug fix, was reading sh2->r[n] */ + UINT32 data = sh2->r[m] & 0x000000ff; + + sh2->r[n] -= 1; + WB( sh2, sh2->r[n], data ); +} + +/* MOV.W Rm,@-Rn */ +INLINE void MOVWM(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 data = sh2->r[m] & 0x0000ffff; + + sh2->r[n] -= 2; + WW( sh2, sh2->r[n], data ); +} + +/* MOV.L Rm,@-Rn */ +INLINE void MOVLM(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 data = sh2->r[m]; + + sh2->r[n] -= 4; + WL( sh2, sh2->r[n], data ); +} + +/* MOV.B @Rm+,Rn */ +INLINE void MOVBP(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->r[m] ); + if (n != m) + sh2->r[m] += 1; +} + +/* MOV.W @Rm+,Rn */ +INLINE void MOVWP(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->r[m] ); + if (n != m) + sh2->r[m] += 2; +} + +/* MOV.L @Rm+,Rn */ +INLINE void MOVLP(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = RL( sh2, sh2->r[m] ); + if (n != m) + sh2->r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +INLINE void MOVBS0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WB( sh2, sh2->ea, sh2->r[m] & 0x000000ff ); +} + +/* MOV.W Rm,@(R0,Rn) */ +INLINE void MOVWS0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WW( sh2, sh2->ea, sh2->r[m] & 0x0000ffff ); +} + +/* MOV.L Rm,@(R0,Rn) */ +INLINE void MOVLS0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[n] + sh2->r[0]; + WL( sh2, sh2->ea, sh2->r[m] ); +} + +/* MOV.B @(R0,Rm),Rn */ +INLINE void MOVBL0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); +} + +/* MOV.W @(R0,Rm),Rn */ +INLINE void MOVWL0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); +} + +/* MOV.L @(R0,Rm),Rn */ +INLINE void MOVLL0(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->ea = sh2->r[m] + sh2->r[0]; + sh2->r[n] = RL( sh2, sh2->ea ); +} + +/* MOV #imm,Rn */ +INLINE void MOVI(sh2_state *sh2, UINT32 i, UINT32 n) +{ + sh2->r[n] = (UINT32)(INT32)(INT16)(INT8) i; +} + +/* MOV.W @(disp8,PC),Rn */ +INLINE void MOVWI(sh2_state *sh2, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->pc + disp * 2 + 2; + sh2->r[n] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); +} + +/* MOV.L @(disp8,PC),Rn */ +INLINE void MOVLI(sh2_state *sh2, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0xff; + sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; + sh2->r[n] = RL( sh2, sh2->ea ); +} + +/* MOV.B @(disp8,GBR),R0 */ +INLINE void MOVBLG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp; + sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); +} + +/* MOV.W @(disp8,GBR),R0 */ +INLINE void MOVWLG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 2; + sh2->r[0] = (INT32)(INT16) RW( sh2, sh2->ea ); +} + +/* MOV.L @(disp8,GBR),R0 */ +INLINE void MOVLLG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 4; + sh2->r[0] = RL( sh2, sh2->ea ); +} + +/* MOV.B R0,@(disp8,GBR) */ +INLINE void MOVBSG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp; + WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp8,GBR) */ +INLINE void MOVWSG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 2; + WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff ); +} + +/* MOV.L R0,@(disp8,GBR) */ +INLINE void MOVLSG(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = sh2->gbr + disp * 4; + WL( sh2, sh2->ea, sh2->r[0] ); +} + +/* MOV.B R0,@(disp4,Rn) */ +INLINE void MOVBS4(sh2_state *sh2, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp; + WB( sh2, sh2->ea, sh2->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp4,Rn) */ +INLINE void MOVWS4(sh2_state *sh2, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp * 2; + WW( sh2, sh2->ea, sh2->r[0] & 0x0000ffff ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +INLINE void MOVLS4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[n] + disp * 4; + WL( sh2, sh2->ea, sh2->r[m] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +INLINE void MOVBL4(sh2_state *sh2, UINT32 m, UINT32 d) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp; + sh2->r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh2, sh2->ea ); +} + +/* MOV.W @(disp4,Rm),R0 */ +INLINE void MOVWL4(sh2_state *sh2, UINT32 m, UINT32 d) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp * 2; + sh2->r[0] = (UINT32)(INT32)(INT16) RW( sh2, sh2->ea ); +} + +/* MOV.L @(disp4,Rm),Rn */ +INLINE void MOVLL4(sh2_state *sh2, UINT32 m, UINT32 d, UINT32 n) +{ + UINT32 disp = d & 0x0f; + sh2->ea = sh2->r[m] + disp * 4; + sh2->r[n] = RL( sh2, sh2->ea ); +} + +/* MOVA @(disp8,PC),R0 */ +INLINE void MOVA(sh2_state *sh2, UINT32 d) +{ + UINT32 disp = d & 0xff; + sh2->ea = ((sh2->pc + 2) & ~3) + disp * 4; + sh2->r[0] = sh2->ea; +} + +/* MOVT Rn */ +INLINE void MOVT(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->sr & T; +} + +/* MUL.L Rm,Rn */ +INLINE void MULL(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->macl = sh2->r[n] * sh2->r[m]; + sh2->icount--; +} + +/* MULS Rm,Rn */ +INLINE void MULS(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->macl = (INT16) sh2->r[n] * (INT16) sh2->r[m]; +} + +/* MULU Rm,Rn */ +INLINE void MULU(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->macl = (UINT16) sh2->r[n] * (UINT16) sh2->r[m]; +} + +/* NEG Rm,Rn */ +INLINE void NEG(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = 0 - sh2->r[m]; +} + +/* NEGC Rm,Rn */ +INLINE void NEGC(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = sh2->r[m]; + sh2->r[n] = -temp - (sh2->sr & T); + if (temp || (sh2->sr & T)) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* NOP */ +INLINE void NOP(void) +{ +} + +/* NOT Rm,Rn */ +INLINE void NOT(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] = ~sh2->r[m]; +} + +/* OR Rm,Rn */ +INLINE void OR(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] |= sh2->r[m]; +} + +/* OR #imm,R0 */ +INLINE void ORI(sh2_state *sh2, UINT32 i) +{ + sh2->r[0] |= i; +} + +/* OR.B #imm,@(R0,GBR) */ +INLINE void ORM(sh2_state *sh2, UINT32 i) +{ + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = RB( sh2, sh2->ea ); + temp |= i; + WB( sh2, sh2->ea, temp ); + sh2->icount -= 2; +} + +/* ROTCL Rn */ +INLINE void ROTCL(sh2_state *sh2, UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[n] >> 31) & T; + sh2->r[n] = (sh2->r[n] << 1) | (sh2->sr & T); + sh2->sr = (sh2->sr & ~T) | temp; +} + +/* ROTCR Rn */ +INLINE void ROTCR(sh2_state *sh2, UINT32 n) +{ + UINT32 temp; + temp = (sh2->sr & T) << 31; + if (sh2->r[n] & T) + sh2->sr |= T; + else + sh2->sr &= ~T; + sh2->r[n] = (sh2->r[n] >> 1) | temp; +} + +/* ROTL Rn */ +INLINE void ROTL(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] = (sh2->r[n] << 1) | (sh2->r[n] >> 31); +} + +/* ROTR Rn */ +INLINE void ROTR(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] = (sh2->r[n] >> 1) | (sh2->r[n] << 31); +} + +/* RTE */ +INLINE void RTE(sh2_state *sh2) +{ + sh2->ea = sh2->r[15]; + sh2->delay = sh2->pc; + sh2->pc = RL( sh2, sh2->ea ); + sh2->r[15] += 4; + sh2->ea = sh2->r[15]; + sh2->sr = RL( sh2, sh2->ea ) & FLAGS; + sh2->r[15] += 4; + sh2->icount -= 3; + sh2->test_irq = 1; +} + +/* RTS */ +INLINE void RTS(sh2_state *sh2) +{ + sh2->delay = sh2->pc; + sh2->pc = sh2->ea = sh2->pr; + sh2->icount--; +} + +/* SETT */ +INLINE void SETT(sh2_state *sh2) +{ + sh2->sr |= T; +} + +/* SHAL Rn (same as SHLL) */ +INLINE void SHAL(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] <<= 1; +} + +/* SHAR Rn */ +INLINE void SHAR(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] = (UINT32)((INT32)sh2->r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +INLINE void SHLL(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | ((sh2->r[n] >> 31) & T); + sh2->r[n] <<= 1; +} + +/* SHLL2 Rn */ +INLINE void SHLL2(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] <<= 2; +} + +/* SHLL8 Rn */ +INLINE void SHLL8(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] <<= 8; +} + +/* SHLL16 Rn */ +INLINE void SHLL16(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] <<= 16; +} + +/* SHLR Rn */ +INLINE void SHLR(sh2_state *sh2, UINT32 n) +{ + sh2->sr = (sh2->sr & ~T) | (sh2->r[n] & T); + sh2->r[n] >>= 1; +} + +/* SHLR2 Rn */ +INLINE void SHLR2(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] >>= 2; +} + +/* SHLR8 Rn */ +INLINE void SHLR8(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] >>= 8; +} + +/* SHLR16 Rn */ +INLINE void SHLR16(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] >>= 16; +} + +/* SLEEP */ +INLINE void SLEEP(sh2_state *sh2) +{ + //if(sh2->sleep_mode != 2) + sh2->pc -= 2; + sh2->icount -= 2; + /* Wait_for_exception; */ + /*if(sh2->sleep_mode == 0) + sh2->sleep_mode = 1; + else if(sh2->sleep_mode == 2) + sh2->sleep_mode = 0;*/ +} + +/* STC SR,Rn */ +INLINE void STCSR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->sr; +} + +/* STC GBR,Rn */ +INLINE void STCGBR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->gbr; +} + +/* STC VBR,Rn */ +INLINE void STCVBR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->vbr; +} + +/* STC.L SR,@-Rn */ +INLINE void STCMSR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->sr ); + sh2->icount--; +} + +/* STC.L GBR,@-Rn */ +INLINE void STCMGBR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->gbr ); + sh2->icount--; +} + +/* STC.L VBR,@-Rn */ +INLINE void STCMVBR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->vbr ); + sh2->icount--; +} + +/* STS MACH,Rn */ +INLINE void STSMACH(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->mach; +} + +/* STS MACL,Rn */ +INLINE void STSMACL(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->macl; +} + +/* STS PR,Rn */ +INLINE void STSPR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] = sh2->pr; +} + +/* STS.L MACH,@-Rn */ +INLINE void STSMMACH(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->mach ); +} + +/* STS.L MACL,@-Rn */ +INLINE void STSMMACL(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->macl ); +} + +/* STS.L PR,@-Rn */ +INLINE void STSMPR(sh2_state *sh2, UINT32 n) +{ + sh2->r[n] -= 4; + sh2->ea = sh2->r[n]; + WL( sh2, sh2->ea, sh2->pr ); +} + +/* SUB Rm,Rn */ +INLINE void SUB(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] -= sh2->r[m]; +} + +/* SUBC Rm,Rn */ +INLINE void SUBC(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 tmp0, tmp1; + + tmp1 = sh2->r[n] - sh2->r[m]; + tmp0 = sh2->r[n]; + sh2->r[n] = tmp1 - (sh2->sr & T); + if (tmp0 < tmp1) + sh2->sr |= T; + else + sh2->sr &= ~T; + if (tmp1 < sh2->r[n]) + sh2->sr |= T; +} + +/* SUBV Rm,Rn */ +INLINE void SUBV(sh2_state *sh2, UINT32 m, UINT32 n) +{ + INT32 dest, src, ans; + + if ((INT32) sh2->r[n] >= 0) + dest = 0; + else + dest = 1; + if ((INT32) sh2->r[m] >= 0) + src = 0; + else + src = 1; + src += dest; + sh2->r[n] -= sh2->r[m]; + if ((INT32) sh2->r[n] >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (src == 1) + { + if (ans == 1) + sh2->sr |= T; + else + sh2->sr &= ~T; + } + else + sh2->sr &= ~T; +} + +/* SWAP.B Rm,Rn */ +INLINE void SWAPB(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 temp0, temp1; + + temp0 = sh2->r[m] & 0xffff0000; + temp1 = (sh2->r[m] & 0x000000ff) << 8; + sh2->r[n] = (sh2->r[m] >> 8) & 0x000000ff; + sh2->r[n] = sh2->r[n] | temp1 | temp0; +} + +/* SWAP.W Rm,Rn */ +INLINE void SWAPW(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[m] >> 16) & 0x0000ffff; + sh2->r[n] = (sh2->r[m] << 16) | temp; +} + +/* TAS.B @Rn */ +INLINE void TAS(sh2_state *sh2, UINT32 n) +{ + UINT32 temp; + sh2->ea = sh2->r[n]; + /* Bus Lock enable */ + temp = RB( sh2, sh2->ea ); + if (temp == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; + temp |= 0x80; + /* Bus Lock disable */ + WB( sh2, sh2->ea, temp ); + sh2->icount -= 3; +} + +/* TRAPA #imm */ +INLINE void TRAPA(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = i & 0xff; + + sh2->ea = sh2->vbr + imm * 4; + + sh2->r[15] -= 4; + WL( sh2, sh2->r[15], sh2->sr ); + sh2->r[15] -= 4; + WL( sh2, sh2->r[15], sh2->pc ); + + sh2->pc = RL( sh2, sh2->ea ); + + sh2->icount -= 7; +} + +/* TST Rm,Rn */ +INLINE void TST(sh2_state *sh2, UINT32 m, UINT32 n) +{ + if ((sh2->r[n] & sh2->r[m]) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* TST #imm,R0 */ +INLINE void TSTI(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = i & 0xff; + + if ((imm & sh2->r[0]) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; +} + +/* TST.B #imm,@(R0,GBR) */ +INLINE void TSTM(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = i & 0xff; + + sh2->ea = sh2->gbr + sh2->r[0]; + if ((imm & RB( sh2, sh2->ea )) == 0) + sh2->sr |= T; + else + sh2->sr &= ~T; + sh2->icount -= 2; +} + +/* XOR Rm,Rn */ +INLINE void XOR(sh2_state *sh2, UINT32 m, UINT32 n) +{ + sh2->r[n] ^= sh2->r[m]; +} + +/* XOR #imm,R0 */ +INLINE void XORI(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = i & 0xff; + sh2->r[0] ^= imm; +} + +/* XOR.B #imm,@(R0,GBR) */ +INLINE void XORM(sh2_state *sh2, UINT32 i) +{ + UINT32 imm = i & 0xff; + UINT32 temp; + + sh2->ea = sh2->gbr + sh2->r[0]; + temp = RB( sh2, sh2->ea ); + temp ^= imm; + WB( sh2, sh2->ea, temp ); + sh2->icount -= 2; +} + +/* XTRCT Rm,Rn */ +INLINE void XTRCT(sh2_state *sh2, UINT32 m, UINT32 n) +{ + UINT32 temp; + + temp = (sh2->r[m] << 16) & 0xffff0000; + sh2->r[n] = (sh2->r[n] >> 16) & 0x0000ffff; + sh2->r[n] |= temp; +} + +/***************************************************************************** + * OPCODE DISPATCHERS + *****************************************************************************/ + +INLINE void op0000(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: ILLEGAL(sh2); rlog(0); break; + case 0x01: ILLEGAL(sh2); rlog(0); break; + case 0x02: STCSR(sh2, Rn); rlog(LRN); break; + case 0x03: BSRF(sh2, Rn); rlog(LRN); break; + case 0x04: MOVBS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x05: MOVWS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x06: MOVLS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x07: MULL(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + case 0x08: CLRT(sh2); rlog(0); break; + case 0x09: NOP(); rlog(0); break; + case 0x0a: STSMACH(sh2, Rn); rlog(LRN); rlog1(SHR_MACH); break; + case 0x0b: RTS(sh2); rlog(0); rlog1(SHR_PR); break; + case 0x0c: MOVBL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x0d: MOVWL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x0e: MOVLL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x0f: MAC_L(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x10: ILLEGAL(sh2); rlog(0); break; + case 0x11: ILLEGAL(sh2); rlog(0); break; + case 0x12: STCGBR(sh2, Rn); rlog(LRN); rlog1(SHR_GBR); break; + case 0x13: ILLEGAL(sh2); rlog(0); break; + case 0x14: MOVBS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x15: MOVWS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x16: MOVLS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x17: MULL(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + case 0x18: SETT(sh2); rlog(0); break; + case 0x19: DIV0U(sh2); rlog(0); break; + case 0x1a: STSMACL(sh2, Rn); rlog(LRN); rlog1(SHR_MACL); break; + case 0x1b: SLEEP(sh2); rlog(0); break; + case 0x1c: MOVBL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x1d: MOVWL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x1e: MOVLL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x1f: MAC_L(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x20: ILLEGAL(sh2); rlog(0); break; + case 0x21: ILLEGAL(sh2); rlog(0); break; + case 0x22: STCVBR(sh2, Rn); rlog(LRN); rlog1(SHR_VBR); break; + case 0x23: BRAF(sh2, Rn); rlog(LRN); break; + case 0x24: MOVBS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x25: MOVWS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x26: MOVLS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x27: MULL(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + case 0x28: CLRMAC(sh2); rlog(0); rlog2(SHR_MACL,SHR_MACH); break; + case 0x29: MOVT(sh2, Rn); rlog(LRN); break; + case 0x2a: STSPR(sh2, Rn); rlog(LRN); rlog1(SHR_PR); break; + case 0x2b: RTE(sh2); rlog(0); break; + case 0x2c: MOVBL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x2d: MOVWL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x2e: MOVLL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x2f: MAC_L(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x30: ILLEGAL(sh2); rlog(0); break; + case 0x31: ILLEGAL(sh2); rlog(0); break; + case 0x32: ILLEGAL(sh2); rlog(0); break; + case 0x33: ILLEGAL(sh2); rlog(0); break; + case 0x34: MOVBS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x35: MOVWS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x36: MOVLS0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x37: MULL(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + case 0x38: ILLEGAL(sh2); rlog(0); break; + case 0x39: ILLEGAL(sh2); rlog(0); break; + case 0x3c: MOVBL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x3d: MOVWL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x3e: MOVLL0(sh2, Rm, Rn); rlog(LRNM); rlog1(0); break; + case 0x3f: MAC_L(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + case 0x3a: ILLEGAL(sh2); rlog(0); break; + case 0x3b: ILLEGAL(sh2); rlog(0); break; + } +} + +INLINE void op0001(sh2_state *sh2, UINT16 opcode) +{ + MOVLS4(sh2, Rm, opcode & 0x0f, Rn); + rlog(LRNM); +} + +INLINE void op0010(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: MOVBS(sh2, Rm, Rn); rlog(LRNM); break; + case 1: MOVWS(sh2, Rm, Rn); rlog(LRNM); break; + case 2: MOVLS(sh2, Rm, Rn); rlog(LRNM); break; + case 3: ILLEGAL(sh2); rlog(0); break; + case 4: MOVBM(sh2, Rm, Rn); rlog(LRNM); break; + case 5: MOVWM(sh2, Rm, Rn); rlog(LRNM); break; + case 6: MOVLM(sh2, Rm, Rn); rlog(LRNM); break; + case 7: DIV0S(sh2, Rm, Rn); rlog(LRNM); break; + case 8: TST(sh2, Rm, Rn); rlog(LRNM); break; + case 9: AND(sh2, Rm, Rn); rlog(LRNM); break; + case 10: XOR(sh2, Rm, Rn); rlog(LRNM); break; + case 11: OR(sh2, Rm, Rn); rlog(LRNM); break; + case 12: CMPSTR(sh2, Rm, Rn); rlog(LRNM); break; + case 13: XTRCT(sh2, Rm, Rn); rlog(LRNM); break; + case 14: MULU(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + case 15: MULS(sh2, Rm, Rn); rlog(LRNM); rlog1(SHR_MACL); break; + } +} + +INLINE void op0011(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: CMPEQ(sh2, Rm, Rn); rlog(LRNM); break; + case 1: ILLEGAL(sh2); rlog(0); break; + case 2: CMPHS(sh2, Rm, Rn); rlog(LRNM); break; + case 3: CMPGE(sh2, Rm, Rn); rlog(LRNM); break; + case 4: DIV1(sh2, Rm, Rn); rlog(LRNM); break; + case 5: DMULU(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + case 6: CMPHI(sh2, Rm, Rn); rlog(LRNM); break; + case 7: CMPGT(sh2, Rm, Rn); rlog(LRNM); break; + case 8: SUB(sh2, Rm, Rn); rlog(LRNM); break; + case 9: ILLEGAL(sh2); rlog(0); break; + case 10: SUBC(sh2, Rm, Rn); rlog(LRNM); break; + case 11: SUBV(sh2, Rm, Rn); rlog(LRNM); break; + case 12: ADD(sh2, Rm, Rn); rlog(LRNM); break; + case 13: DMULS(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + case 14: ADDC(sh2, Rm, Rn); rlog(LRNM); break; + case 15: ADDV(sh2, Rm, Rn); rlog(LRNM); break; + } +} + +INLINE void op0100(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: SHLL(sh2, Rn); rlog(LRN); break; + case 0x01: SHLR(sh2, Rn); rlog(LRN); break; + case 0x02: STSMMACH(sh2, Rn); rlog(LRN); rlog1(SHR_MACH); break; + case 0x03: STCMSR(sh2, Rn); rlog(LRN); break; + case 0x04: ROTL(sh2, Rn); rlog(LRN); break; + case 0x05: ROTR(sh2, Rn); rlog(LRN); break; + case 0x06: LDSMMACH(sh2, Rn); rlog(LRN); rlog1(SHR_MACH); break; + case 0x07: LDCMSR(sh2, Rn); rlog(LRN); break; + case 0x08: SHLL2(sh2, Rn); rlog(LRN); break; + case 0x09: SHLR2(sh2, Rn); rlog(LRN); break; + case 0x0a: LDSMACH(sh2, Rn); rlog(LRN); rlog1(SHR_MACH); break; + case 0x0b: JSR(sh2, Rn); rlog(LRN); rlog1(SHR_PR); break; + case 0x0c: ILLEGAL(sh2); rlog(0); break; + case 0x0d: ILLEGAL(sh2); rlog(0); break; + case 0x0e: LDCSR(sh2, Rn); rlog(LRN); break; + case 0x0f: MAC_W(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x10: DT(sh2, Rn); rlog(LRN); break; + case 0x11: CMPPZ(sh2, Rn); rlog(LRN); break; + case 0x12: STSMMACL(sh2, Rn); rlog(LRN); rlog1(SHR_MACL); break; + case 0x13: STCMGBR(sh2, Rn); rlog(LRN); rlog1(SHR_GBR); break; + case 0x14: ILLEGAL(sh2); rlog(0); break; + case 0x15: CMPPL(sh2, Rn); rlog(LRN); break; + case 0x16: LDSMMACL(sh2, Rn); rlog(LRN); rlog1(SHR_MACL); break; + case 0x17: LDCMGBR(sh2, Rn); rlog(LRN); rlog1(SHR_GBR); break; + case 0x18: SHLL8(sh2, Rn); rlog(LRN); break; + case 0x19: SHLR8(sh2, Rn); rlog(LRN); break; + case 0x1a: LDSMACL(sh2, Rn); rlog(LRN); rlog1(SHR_MACL); break; + case 0x1b: TAS(sh2, Rn); rlog(LRN); break; + case 0x1c: ILLEGAL(sh2); rlog(0); break; + case 0x1d: ILLEGAL(sh2); rlog(0); break; + case 0x1e: LDCGBR(sh2, Rn); rlog(LRN); rlog1(SHR_GBR); break; + case 0x1f: MAC_W(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x20: SHAL(sh2, Rn); rlog(LRN); break; + case 0x21: SHAR(sh2, Rn); rlog(LRN); break; + case 0x22: STSMPR(sh2, Rn); rlog(LRN); rlog1(SHR_PR); break; + case 0x23: STCMVBR(sh2, Rn); rlog(LRN); rlog1(SHR_VBR); break; + case 0x24: ROTCL(sh2, Rn); rlog(LRN); break; + case 0x25: ROTCR(sh2, Rn); rlog(LRN); break; + case 0x26: LDSMPR(sh2, Rn); rlog(LRN); rlog1(SHR_PR); break; + case 0x27: LDCMVBR(sh2, Rn); rlog(LRN); rlog1(SHR_VBR); break; + case 0x28: SHLL16(sh2, Rn); rlog(LRN); break; + case 0x29: SHLR16(sh2, Rn); rlog(LRN); break; + case 0x2a: LDSPR(sh2, Rn); rlog(LRN); rlog1(SHR_PR); break; + case 0x2b: JMP(sh2, Rn); rlog(LRN); break; + case 0x2c: ILLEGAL(sh2); rlog(0); break; + case 0x2d: ILLEGAL(sh2); rlog(0); break; + case 0x2e: LDCVBR(sh2, Rn); rlog(LRN); rlog1(SHR_VBR); break; + case 0x2f: MAC_W(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: ILLEGAL(sh2); rlog(0); break; + case 0x3f: MAC_W(sh2, Rm, Rn); rlog(LRNM); rlog2(SHR_MACL,SHR_MACH); break; + } +} + +INLINE void op0101(sh2_state *sh2, UINT16 opcode) +{ + MOVLL4(sh2, Rm, opcode & 0x0f, Rn); + rlog(LRNM); +} + +INLINE void op0110(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & 15) + { + case 0: MOVBL(sh2, Rm, Rn); break; + case 1: MOVWL(sh2, Rm, Rn); break; + case 2: MOVLL(sh2, Rm, Rn); break; + case 3: MOV(sh2, Rm, Rn); break; + case 4: MOVBP(sh2, Rm, Rn); break; + case 5: MOVWP(sh2, Rm, Rn); break; + case 6: MOVLP(sh2, Rm, Rn); break; + case 7: NOT(sh2, Rm, Rn); break; + case 8: SWAPB(sh2, Rm, Rn); break; + case 9: SWAPW(sh2, Rm, Rn); break; + case 10: NEGC(sh2, Rm, Rn); break; + case 11: NEG(sh2, Rm, Rn); break; + case 12: EXTUB(sh2, Rm, Rn); break; + case 13: EXTUW(sh2, Rm, Rn); break; + case 14: EXTSB(sh2, Rm, Rn); break; + case 15: EXTSW(sh2, Rm, Rn); break; + } + rlog(LRNM); +} + +INLINE void op0111(sh2_state *sh2, UINT16 opcode) +{ + ADDI(sh2, opcode & 0xff, Rn); + rlog(LRN); +} + +INLINE void op1000(sh2_state *sh2, UINT16 opcode) +{ + switch ( opcode & (15<<8) ) + { + case 0<< 8: MOVBS4(sh2, opcode & 0x0f, Rm); rlog(LRM); rlog1(0); break; + case 1<< 8: MOVWS4(sh2, opcode & 0x0f, Rm); rlog(LRM); rlog1(0); break; + case 2<< 8: ILLEGAL(sh2); rlog(0); break; + case 3<< 8: ILLEGAL(sh2); rlog(0); break; + case 4<< 8: MOVBL4(sh2, Rm, opcode & 0x0f); rlog(LRM); rlog1(0); break; + case 5<< 8: MOVWL4(sh2, Rm, opcode & 0x0f); rlog(LRM); rlog1(0); break; + case 6<< 8: ILLEGAL(sh2); rlog(0); break; + case 7<< 8: ILLEGAL(sh2); rlog(0); break; + case 8<< 8: CMPIM(sh2, opcode & 0xff); rlog(0); rlog1(0); break; + case 9<< 8: BT(sh2, opcode & 0xff); rlog(0); break; + case 10<< 8: ILLEGAL(sh2); rlog(0); break; + case 11<< 8: BF(sh2, opcode & 0xff); rlog(0); break; + case 12<< 8: ILLEGAL(sh2); rlog(0); break; + case 13<< 8: BTS(sh2, opcode & 0xff); rlog(0); break; + case 14<< 8: ILLEGAL(sh2); rlog(0); break; + case 15<< 8: BFS(sh2, opcode & 0xff); rlog(0); break; + } +} + + +INLINE void op1001(sh2_state *sh2, UINT16 opcode) +{ + MOVWI(sh2, opcode & 0xff, Rn); + rlog(LRN); +} + +INLINE void op1010(sh2_state *sh2, UINT16 opcode) +{ + BRA(sh2, opcode & 0xfff); + rlog(0); +} + +INLINE void op1011(sh2_state *sh2, UINT16 opcode) +{ + BSR(sh2, opcode & 0xfff); + rlog(0); + rlog1(SHR_PR); +} + +INLINE void op1100(sh2_state *sh2, UINT16 opcode) +{ + switch (opcode & (15<<8)) + { + case 0<<8: MOVBSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 1<<8: MOVWSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 2<<8: MOVLSG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 3<<8: TRAPA(sh2, opcode & 0xff); rlog1(SHR_VBR); break; + case 4<<8: MOVBLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 5<<8: MOVWLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 6<<8: MOVLLG(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 7<<8: MOVA(sh2, opcode & 0xff); rlog1(0); break; + case 8<<8: TSTI(sh2, opcode & 0xff); rlog1(0); break; + case 9<<8: ANDI(sh2, opcode & 0xff); rlog1(0); break; + case 10<<8: XORI(sh2, opcode & 0xff); rlog1(0); break; + case 11<<8: ORI(sh2, opcode & 0xff); rlog1(0); break; + case 12<<8: TSTM(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 13<<8: ANDM(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 14<<8: XORM(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + case 15<<8: ORM(sh2, opcode & 0xff); rlog2(0, SHR_GBR); break; + } + rlog(0); +} + +INLINE void op1101(sh2_state *sh2, UINT16 opcode) +{ + MOVLI(sh2, opcode & 0xff, Rn); + rlog(LRN); +} + +INLINE void op1110(sh2_state *sh2, UINT16 opcode) +{ + MOVI(sh2, opcode & 0xff, Rn); + rlog(LRN); +} + +INLINE void op1111(sh2_state *sh2, UINT16 opcode) +{ + ILLEGAL(sh2); + rlog(0); +} + +#endif diff --git a/waterbox/picodrive/cpu/sh2/mame/sh2pico.c b/waterbox/picodrive/cpu/sh2/mame/sh2pico.c new file mode 100644 index 0000000000..8b543e8224 --- /dev/null +++ b/waterbox/picodrive/cpu/sh2/mame/sh2pico.c @@ -0,0 +1,326 @@ +#include "../sh2.h" + +#ifdef DRC_CMP +#include "../compiler.c" +#define BUSY_LOOP_HACKS 0 +#else +#define BUSY_LOOP_HACKS 1 +#endif + +// MAME types +#ifndef INT8 +typedef signed char INT8; +typedef signed short INT16; +typedef signed int INT32; +typedef unsigned int UINT32; +typedef unsigned short UINT16; +typedef unsigned char UINT8; +#endif + +#ifdef DRC_SH2 + +// this nasty conversion is needed for drc-expecting memhandlers +#define MAKE_READFUNC(name, cname) \ +static inline unsigned int name(SH2 *sh2, unsigned int a) \ +{ \ + unsigned int ret; \ + sh2->sr |= sh2->icount << 12; \ + ret = cname(a, sh2); \ + sh2->icount = (signed int)sh2->sr >> 12; \ + sh2->sr &= 0x3f3; \ + return ret; \ +} + +#define MAKE_WRITEFUNC(name, cname) \ +static inline void name(SH2 *sh2, unsigned int a, unsigned int d) \ +{ \ + sh2->sr |= sh2->icount << 12; \ + cname(a, d, sh2); \ + sh2->icount = (signed int)sh2->sr >> 12; \ + sh2->sr &= 0x3f3; \ +} + +MAKE_READFUNC(RB, p32x_sh2_read8) +MAKE_READFUNC(RW, p32x_sh2_read16) +MAKE_READFUNC(RL, p32x_sh2_read32) +MAKE_WRITEFUNC(WB, p32x_sh2_write8) +MAKE_WRITEFUNC(WW, p32x_sh2_write16) +MAKE_WRITEFUNC(WL, p32x_sh2_write32) + +#else + +#define RB(sh2, a) p32x_sh2_read8(a, sh2) +#define RW(sh2, a) p32x_sh2_read16(a, sh2) +#define RL(sh2, a) p32x_sh2_read32(a, sh2) +#define WB(sh2, a, d) p32x_sh2_write8(a, d, sh2) +#define WW(sh2, a, d) p32x_sh2_write16(a, d, sh2) +#define WL(sh2, a, d) p32x_sh2_write32(a, d, sh2) + +#endif + +// some stuff from sh2comn.h +#define T 0x00000001 +#define S 0x00000002 +#define I 0x000000f0 +#define Q 0x00000100 +#define M 0x00000200 + +#define AM 0xc7ffffff + +#define FLAGS (M|Q|I|S|T) + +#define Rn ((opcode>>8)&15) +#define Rm ((opcode>>4)&15) + +#define sh2_state SH2 + +extern void lprintf(const char *fmt, ...); +#define logerror lprintf + +#ifdef SH2_STATS +static SH2 sh2_stats; +static unsigned int op_refs[0x10000]; +# define LRN 1 +# define LRM 2 +# define LRNM (LRN|LRM) +# define rlog(rnm) { \ + int op = opcode; \ + if ((rnm) & LRN) { \ + op &= ~0x0f00; \ + sh2_stats.r[Rn]++; \ + } \ + if ((rnm) & LRM) { \ + op &= ~0x00f0; \ + sh2_stats.r[Rm]++; \ + } \ + op_refs[op]++; \ +} +# define rlog1(x) sh2_stats.r[x]++ +# define rlog2(x1,x2) sh2_stats.r[x1]++; sh2_stats.r[x2]++ +#else +# define rlog(x) +# define rlog1(...) +# define rlog2(...) +#endif + +#include "sh2.inc" + +#ifndef DRC_CMP + +int sh2_execute_interpreter(SH2 *sh2, int cycles) +{ + UINT32 opcode; + + sh2->icount = cycles; + + if (sh2->icount <= 0) + goto out; + + do + { + if (sh2->delay) + { + sh2->ppc = sh2->delay; + opcode = RW(sh2, sh2->delay); + sh2->pc -= 2; + } + else + { + sh2->ppc = sh2->pc; + opcode = RW(sh2, sh2->pc); + } + + sh2->delay = 0; + sh2->pc += 2; + + switch (opcode & ( 15 << 12)) + { + case 0<<12: op0000(sh2, opcode); break; + case 1<<12: op0001(sh2, opcode); break; + case 2<<12: op0010(sh2, opcode); break; + case 3<<12: op0011(sh2, opcode); break; + case 4<<12: op0100(sh2, opcode); break; + case 5<<12: op0101(sh2, opcode); break; + case 6<<12: op0110(sh2, opcode); break; + case 7<<12: op0111(sh2, opcode); break; + case 8<<12: op1000(sh2, opcode); break; + case 9<<12: op1001(sh2, opcode); break; + case 10<<12: op1010(sh2, opcode); break; + case 11<<12: op1011(sh2, opcode); break; + case 12<<12: op1100(sh2, opcode); break; + case 13<<12: op1101(sh2, opcode); break; + case 14<<12: op1110(sh2, opcode); break; + default: op1111(sh2, opcode); break; + } + + sh2->icount--; + + if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) + { + int level = sh2->pending_level; + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + sh2->test_irq = 0; + } + + } + while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */ + +out: + return sh2->icount; +} + +#else // if DRC_CMP + +int sh2_execute_interpreter(SH2 *sh2, int cycles) +{ + static unsigned int base_pc_[2] = { 0, 0 }; + static unsigned int end_pc_[2] = { 0, 0 }; + static unsigned char op_flags_[2][BLOCK_INSN_LIMIT]; + unsigned int *base_pc = &base_pc_[sh2->is_slave]; + unsigned int *end_pc = &end_pc_[sh2->is_slave]; + unsigned char *op_flags = op_flags_[sh2->is_slave]; + unsigned int pc_expect; + UINT32 opcode; + + sh2->icount = sh2->cycles_timeslice = cycles; + + if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) + { + int level = sh2->pending_level; + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + } + pc_expect = sh2->pc; + + if (sh2->icount <= 0) + goto out; + + do + { + if (!sh2->delay) { + if (sh2->pc < *base_pc || sh2->pc >= *end_pc) { + *base_pc = sh2->pc; + scan_block(*base_pc, sh2->is_slave, + op_flags, end_pc, NULL); + } + if ((op_flags[(sh2->pc - *base_pc) / 2] + & OF_BTARGET) || sh2->pc == *base_pc + || pc_expect != sh2->pc) // branched + { + pc_expect = sh2->pc; + if (sh2->icount < 0) + break; + } + + do_sh2_trace(sh2, sh2->icount); + } + pc_expect += 2; + + if (sh2->delay) + { + sh2->ppc = sh2->delay; + opcode = RW(sh2, sh2->delay); + sh2->pc -= 2; + } + else + { + sh2->ppc = sh2->pc; + opcode = RW(sh2, sh2->pc); + } + + sh2->delay = 0; + sh2->pc += 2; + + switch (opcode & ( 15 << 12)) + { + case 0<<12: op0000(sh2, opcode); break; + case 1<<12: op0001(sh2, opcode); break; + case 2<<12: op0010(sh2, opcode); break; + case 3<<12: op0011(sh2, opcode); break; + case 4<<12: op0100(sh2, opcode); break; + case 5<<12: op0101(sh2, opcode); break; + case 6<<12: op0110(sh2, opcode); break; + case 7<<12: op0111(sh2, opcode); break; + case 8<<12: op1000(sh2, opcode); break; + case 9<<12: op1001(sh2, opcode); break; + case 10<<12: op1010(sh2, opcode); break; + case 11<<12: op1011(sh2, opcode); break; + case 12<<12: op1100(sh2, opcode); break; + case 13<<12: op1101(sh2, opcode); break; + case 14<<12: op1110(sh2, opcode); break; + default: op1111(sh2, opcode); break; + } + + sh2->icount--; + + if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f)) + { + int level = sh2->pending_level; + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + sh2->test_irq = 0; + } + + } + while (1); + +out: + return sh2->icount; +} + +#endif // DRC_CMP + +#ifdef SH2_STATS +#include +#include +#include "sh2dasm.h" + +void sh2_dump_stats(void) +{ + static const char *rnames[] = { + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "SP", + "PC", "", "PR", "SR", "GBR", "VBR", "MACH", "MACL" + }; + long long total; + char buff[64]; + int u, i; + + // dump reg usage + total = 0; + for (i = 0; i < 24; i++) + total += sh2_stats.r[i]; + + for (i = 0; i < 24; i++) { + if (i == 16 || i == 17 || i == 19) + continue; + printf("r %6.3f%% %-4s %9d\n", (double)sh2_stats.r[i] * 100.0 / total, + rnames[i], sh2_stats.r[i]); + } + + memset(&sh2_stats, 0, sizeof(sh2_stats)); + + // dump ops + printf("\n"); + total = 0; + for (i = 0; i < 0x10000; i++) + total += op_refs[i]; + + for (u = 0; u < 16; u++) { + int max = 0, op = 0; + for (i = 0; i < 0x10000; i++) { + if (op_refs[i] > max) { + max = op_refs[i]; + op = i; + } + } + DasmSH2(buff, 0, op); + printf("i %6.3f%% %9d %s\n", (double)op_refs[op] * 100.0 / total, + op_refs[op], buff); + op_refs[op] = 0; + } + memset(op_refs, 0, sizeof(op_refs)); +} +#endif + diff --git a/waterbox/picodrive/cpu/sh2/sh2.c b/waterbox/picodrive/cpu/sh2/sh2.c new file mode 100644 index 0000000000..ef3914b863 --- /dev/null +++ b/waterbox/picodrive/cpu/sh2/sh2.c @@ -0,0 +1,346 @@ +/* + * PicoDrive + * (C) notaz, 2009,2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include +#include + +#include "sh2.h" + +#define I 0xf0 + +int sh2_init(SH2 *sh2, int is_slave, SH2 *other_sh2) +{ + int ret = 0; + unsigned int mult_m68k_to_sh2 = sh2->mult_m68k_to_sh2; + unsigned int mult_sh2_to_m68k = sh2->mult_sh2_to_m68k; + + memset(sh2, 0, sizeof(*sh2)); + sh2->is_slave = is_slave; + sh2->other_sh2 = other_sh2; + sh2->mult_m68k_to_sh2 = mult_m68k_to_sh2; + sh2->mult_sh2_to_m68k = mult_sh2_to_m68k; + + return ret; +} + +void sh2_finish(SH2 *sh2) +{ +#ifdef DRC_SH2 + sh2_drc_finish(sh2); +#endif +} + +void sh2_reset(SH2 *sh2) +{ + sh2->pc = p32x_sh2_read32(0, sh2); + sh2->r[15] = p32x_sh2_read32(4, sh2); + sh2->sr = I; + sh2->vbr = 0; + sh2->pending_int_irq = 0; +} + +void sh2_do_irq(SH2 *sh2, int level, int vector) +{ + sh2->sr &= 0x3f3; + + sh2->r[15] -= 4; + p32x_sh2_write32(sh2->r[15], sh2->sr, sh2); /* push SR onto stack */ + sh2->r[15] -= 4; + p32x_sh2_write32(sh2->r[15], sh2->pc, sh2); /* push PC onto stack */ + + /* set I flags in SR */ + sh2->sr = (sh2->sr & ~I) | (level << 4); + + /* fetch PC */ + sh2->pc = p32x_sh2_read32(sh2->vbr + vector * 4, sh2); + + /* 13 cycles at best */ + sh2->icount -= 13; +} + +int sh2_irl_irq(SH2 *sh2, int level, int nested_call) +{ + int taken; + + sh2->pending_irl = level; + if (level < sh2->pending_int_irq) + level = sh2->pending_int_irq; + sh2->pending_level = level; + + taken = (level > ((sh2->sr >> 4) & 0x0f)); + if (taken) { + if (!nested_call) { + // not in memhandler, so handle this now (recompiler friendly) + // do this to avoid missing irqs that other SH2 might clear + int vector = sh2->irq_callback(sh2, level); + sh2_do_irq(sh2, level, vector); + sh2->m68krcycles_done += C_SH2_TO_M68K(*sh2, 13); + } + else + sh2->test_irq = 1; + } + return taken; +} + +void sh2_internal_irq(SH2 *sh2, int level, int vector) +{ + // FIXME: multiple internal irqs not handled.. + // assuming internal irqs never clear until accepted + sh2->pending_int_irq = level; + sh2->pending_int_vector = vector; + if (level > sh2->pending_level) + sh2->pending_level = level; + + sh2->test_irq = 1; +} + +#define SH2_REG_SIZE (offsetof(SH2, macl) + sizeof(sh2->macl)) + +void sh2_pack(const SH2 *sh2, unsigned char *buff) +{ + unsigned int *p; + + memcpy(buff, sh2, SH2_REG_SIZE); + p = (void *)(buff + SH2_REG_SIZE); + + p[0] = sh2->pending_int_irq; + p[1] = sh2->pending_int_vector; +} + +void sh2_unpack(SH2 *sh2, const unsigned char *buff) +{ + unsigned int *p; + + memcpy(sh2, buff, SH2_REG_SIZE); + p = (void *)(buff + SH2_REG_SIZE); + + sh2->pending_int_irq = p[0]; + sh2->pending_int_vector = p[1]; + sh2->test_irq = 1; +} + +#ifdef DRC_CMP + +/* trace/compare */ +#include +#include +#include +#undef _USE_CZ80 // HACK +#include +#include + +static SH2 sh2ref[2]; +static unsigned int mem_val; + +static unsigned int local_read32(SH2 *sh2, u32 a) +{ + const sh2_memmap *sh2_map = sh2->read16_map; + u16 *pd; + uptr p; + + sh2_map += (a >> 25); + p = sh2_map->addr; + if (!map_flag_set(p)) { + pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1)); + return (pd[0] << 16) | pd[1]; + } + + if ((a & 0xfffff000) == 0xc0000000) { + // data array + pd = (u16 *)sh2->data_array + (a & 0xfff) / 2; + return (pd[0] << 16) | pd[1]; + } + if ((a & 0xdfffffc0) == 0x4000) { + pd = &Pico32x.regs[(a & 0x3f) / 2]; + return (pd[0] << 16) | pd[1]; + } + if ((a & 0xdffffe00) == 0x4200) { + pd = &Pico32xMem->pal[(a & 0x1ff) / 2]; + return (pd[0] << 16) | pd[1]; + } + + return 0; +} + +void do_sh2_trace(SH2 *current, int cycles) +{ + static int current_slave = -1; + static u32 current_m68k_pc; + SH2 *sh2o = &sh2ref[current->is_slave]; + u32 *regs_a = (void *)current; + u32 *regs_o = (void *)sh2o; + unsigned char v; + u32 val; + int i; + + if (SekPc != current_m68k_pc) { + current_m68k_pc = SekPc; + tl_write_uint(CTL_M68KPC, current_m68k_pc); + } + + if (current->is_slave != current_slave) { + current_slave = current->is_slave; + v = CTL_MASTERSLAVE | current->is_slave; + tl_write(&v, sizeof(v)); + } + + for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) { + if (i == 17) // ppc + continue; + if (regs_a[i] != regs_o[i]) { + tl_write_uint(CTL_SH2_R + i, regs_a[i]); + regs_o[i] = regs_a[i]; + } + } + + if (current->ea != sh2o->ea) { + tl_write_uint(CTL_EA, current->ea); + sh2o->ea = current->ea; + } + val = local_read32(current, current->ea); + if (mem_val != val) { + tl_write_uint(CTL_EAVAL, val); + mem_val = val; + } + tl_write_uint(CTL_CYCLES, cycles); +} + +static const char *regnames[] = { + "r0", "r1", "r2", "r3", + "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15", + "pc", "ppc", "pr", "sr", + "gbr", "vbr", "mach","macl", +}; + +static void dump_regs(SH2 *sh2) +{ + char csh2; + int i; + + csh2 = sh2->is_slave ? 's' : 'm'; + for (i = 0; i < 16/2; i++) + printf("%csh2 r%d: %08x r%02d: %08x\n", csh2, + i, sh2->r[i], i+8, sh2->r[i+8]); + printf("%csh2 PC: %08x , %08x\n", csh2, sh2->pc, sh2->ppc); + printf("%csh2 SR: %03x PR: %08x\n", csh2, sh2->sr, sh2->pr); +} + +void do_sh2_cmp(SH2 *current) +{ + static int current_slave; + static u32 current_val; + SH2 *sh2o = &sh2ref[current->is_slave]; + u32 *regs_a = (void *)current; + u32 *regs_o = (void *)sh2o; + unsigned char code; + int cycles_o = 666; + u32 sr, val; + int bad = 0; + int cycles; + int i, ret; + + sh2ref[1].is_slave = 1; + + while (1) { + ret = tl_read(&code, 1); + if (ret <= 0) + break; + if (code == CTL_CYCLES) { + tl_read(&cycles_o, 4); + break; + } + + switch (code) { + case CTL_MASTERSLAVE: + case CTL_MASTERSLAVE + 1: + current_slave = code & 1; + break; + case CTL_EA: + tl_read_uint(&sh2o->ea); + break; + case CTL_EAVAL: + tl_read_uint(¤t_val); + break; + case CTL_M68KPC: + tl_read_uint(&val); + if (SekPc != val) { + printf("m68k: %08x %08x\n", SekPc, val); + bad = 1; + } + break; + default: + if (CTL_SH2_R <= code && code < CTL_SH2_R + + offsetof(SH2, read8_map) / 4) + { + tl_read_uint(regs_o + code - CTL_SH2_R); + } + else + { + printf("wrong code: %02x\n", code); + goto end; + } + break; + } + } + + if (ret <= 0) { + printf("EOF?\n"); + goto end; + } + + if (current->is_slave != current_slave) { + printf("bad slave: %d %d\n", current->is_slave, + current_slave); + bad = 1; + } + + for (i = 0; i < offsetof(SH2, read8_map) / 4; i++) { + if (i == 17 || i == 19) // ppc, sr + continue; + if (regs_a[i] != regs_o[i]) { + printf("bad %4s: %08x %08x\n", + regnames[i], regs_a[i], regs_o[i]); + bad = 1; + } + } + + sr = current->sr & 0x3f3; + cycles = (signed int)current->sr >> 12; + + if (sr != sh2o->sr) { + printf("bad SR: %03x %03x\n", sr, sh2o->sr); + bad = 1; + } + + if (cycles != cycles_o) { + printf("bad cycles: %d %d\n", cycles, cycles_o); + bad = 1; + } + + val = local_read32(current, sh2o->ea); + if (val != current_val) { + printf("bad val @%08x: %08x %08x\n", sh2o->ea, val, current_val); + bad = 1; + } + + if (!bad) { + sh2o->ppc = current->pc; + return; + } + +end: + printf("--\n"); + dump_regs(sh2o); + if (current->is_slave != current_slave) + dump_regs(&sh2ref[current->is_slave ^ 1]); + PDebugDumpMem(); + exit(1); +} + +#endif // DRC_CMP diff --git a/waterbox/picodrive/cpu/sh2/sh2.h b/waterbox/picodrive/cpu/sh2/sh2.h new file mode 100644 index 0000000000..362234b1a7 --- /dev/null +++ b/waterbox/picodrive/cpu/sh2/sh2.h @@ -0,0 +1,119 @@ +#ifndef __SH2_H__ +#define __SH2_H__ + +#if !defined(REGPARM) && defined(__i386__) +#define REGPARM(x) __attribute__((regparm(x))) +#else +#define REGPARM(x) +#endif + +// registers - matches structure order +typedef enum { + SHR_R0 = 0, SHR_SP = 15, + SHR_PC, SHR_PPC, SHR_PR, SHR_SR, + SHR_GBR, SHR_VBR, SHR_MACH, SHR_MACL, +} sh2_reg_e; + +typedef struct SH2_ +{ + unsigned int r[16]; // 00 + unsigned int pc; // 40 + unsigned int ppc; + unsigned int pr; + unsigned int sr; + unsigned int gbr, vbr; // 50 + unsigned int mach, macl; // 58 + + // common + const void *read8_map; // 60 + const void *read16_map; + const void **write8_tab; + const void **write16_tab; + +#define SH2_STATE_RUN (1 << 0) // to prevent recursion +#define SH2_STATE_SLEEP (1 << 1) +#define SH2_STATE_CPOLL (1 << 2) // polling comm regs +#define SH2_STATE_VPOLL (1 << 3) // polling VDP + unsigned int state; + unsigned int poll_addr; + int poll_cycles; + int poll_cnt; + + // interpreter stuff + int icount; // cycles left in current timeslice + unsigned int ea; + unsigned int delay; + unsigned int test_irq; + + int pending_level; // MAX(pending_irl, pending_int_irq) + int pending_irl; + int pending_int_irq; // internal irq + int pending_int_vector; + int REGPARM(2) (*irq_callback)(struct SH2_ *sh2, int level); + int is_slave; + + unsigned int cycles_timeslice; + + struct SH2_ *other_sh2; + + // we use 68k reference cycles for easier sync + unsigned int m68krcycles_done; + unsigned int mult_m68k_to_sh2; + unsigned int mult_sh2_to_m68k; + + unsigned char data_array[0x1000]; // cache (can be used as RAM) + unsigned int peri_regs[0x200/4]; // periphereal regs +} SH2; + +#define CYCLE_MULT_SHIFT 10 +#define C_M68K_TO_SH2(xsh2, c) \ + ((int)((c) * (xsh2).mult_m68k_to_sh2) >> CYCLE_MULT_SHIFT) +#define C_SH2_TO_M68K(xsh2, c) \ + ((int)((c + 3) * (xsh2).mult_sh2_to_m68k) >> CYCLE_MULT_SHIFT) + +int sh2_init(SH2 *sh2, int is_slave, SH2 *other_sh2); +void sh2_finish(SH2 *sh2); +void sh2_reset(SH2 *sh2); +int sh2_irl_irq(SH2 *sh2, int level, int nested_call); +void sh2_internal_irq(SH2 *sh2, int level, int vector); +void sh2_do_irq(SH2 *sh2, int level, int vector); +void sh2_pack(const SH2 *sh2, unsigned char *buff); +void sh2_unpack(SH2 *sh2, const unsigned char *buff); + +int sh2_execute_drc(SH2 *sh2c, int cycles); +int sh2_execute_interpreter(SH2 *sh2c, int cycles); + +static inline int sh2_execute(SH2 *sh2, int cycles, int use_drc) +{ + int ret; + + sh2->cycles_timeslice = cycles; +#ifdef DRC_SH2 + if (use_drc) + ret = sh2_execute_drc(sh2, cycles); + else +#endif + ret = sh2_execute_interpreter(sh2, cycles); + + return sh2->cycles_timeslice - ret; +} + +// regs, pending_int*, cycles, reserved +#define SH2_STATE_SIZE ((24 + 2 + 2 + 12) * 4) + +// pico memhandlers +// XXX: move somewhere else +unsigned int REGPARM(2) p32x_sh2_read8(unsigned int a, SH2 *sh2); +unsigned int REGPARM(2) p32x_sh2_read16(unsigned int a, SH2 *sh2); +unsigned int REGPARM(2) p32x_sh2_read32(unsigned int a, SH2 *sh2); +void REGPARM(3) p32x_sh2_write8 (unsigned int a, unsigned int d, SH2 *sh2); +void REGPARM(3) p32x_sh2_write16(unsigned int a, unsigned int d, SH2 *sh2); +void REGPARM(3) p32x_sh2_write32(unsigned int a, unsigned int d, SH2 *sh2); + +// debug +#ifdef DRC_CMP +void do_sh2_trace(SH2 *current, int cycles); +void do_sh2_cmp(SH2 *current); +#endif + +#endif /* __SH2_H__ */ diff --git a/waterbox/picodrive/pico/32x/32x.c b/waterbox/picodrive/pico/32x/32x.c new file mode 100644 index 0000000000..50360d145c --- /dev/null +++ b/waterbox/picodrive/pico/32x/32x.c @@ -0,0 +1,562 @@ +/* + * PicoDrive + * (C) notaz, 2009,2010,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include "../pico_int.h" +#include "../sound/ym2612.h" + +struct Pico32x Pico32x; +SH2 sh2s[2]; + +#define SH2_IDLE_STATES (SH2_STATE_CPOLL|SH2_STATE_VPOLL|SH2_STATE_SLEEP) + +static int REGPARM(2) sh2_irq_cb(SH2 *sh2, int level) +{ + if (sh2->pending_irl > sh2->pending_int_irq) { + elprintf_sh2(sh2, EL_32X, "ack/irl %d @ %08x", + level, sh2_pc(sh2)); + return 64 + sh2->pending_irl / 2; + } else { + elprintf_sh2(sh2, EL_32X, "ack/int %d/%d @ %08x", + level, sh2->pending_int_vector, sh2_pc(sh2)); + sh2->pending_int_irq = 0; // auto-clear + sh2->pending_level = sh2->pending_irl; + return sh2->pending_int_vector; + } +} + +// MUST specify active_sh2 when called from sh2 memhandlers +void p32x_update_irls(SH2 *active_sh2, int m68k_cycles) +{ + int irqs, mlvl = 0, slvl = 0; + int mrun, srun; + + if (active_sh2 != NULL) + m68k_cycles = sh2_cycles_done_m68k(active_sh2); + + // msh2 + irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[0]; + while ((irqs >>= 1)) + mlvl++; + mlvl *= 2; + + // ssh2 + irqs = Pico32x.sh2irqs | Pico32x.sh2irqi[1]; + while ((irqs >>= 1)) + slvl++; + slvl *= 2; + + mrun = sh2_irl_irq(&msh2, mlvl, active_sh2 == &msh2); + if (mrun) { + p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, m68k_cycles); + if (active_sh2 == &msh2) + sh2_end_run(active_sh2, 1); + } + + srun = sh2_irl_irq(&ssh2, slvl, active_sh2 == &ssh2); + if (srun) { + p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, m68k_cycles); + if (active_sh2 == &ssh2) + sh2_end_run(active_sh2, 1); + } + + elprintf(EL_32X, "update_irls: m %d/%d, s %d/%d", mlvl, mrun, slvl, srun); +} + +// the mask register is inconsistent, CMD is supposed to be a mask, +// while others are actually irq trigger enables? +// TODO: test on hw.. +void p32x_trigger_irq(SH2 *sh2, int m68k_cycles, unsigned int mask) +{ + Pico32x.sh2irqs |= mask & P32XI_VRES; + Pico32x.sh2irqi[0] |= mask & (Pico32x.sh2irq_mask[0] << 3); + Pico32x.sh2irqi[1] |= mask & (Pico32x.sh2irq_mask[1] << 3); + + p32x_update_irls(sh2, m68k_cycles); +} + +void p32x_update_cmd_irq(SH2 *sh2, int m68k_cycles) +{ + if ((Pico32x.sh2irq_mask[0] & 2) && (Pico32x.regs[2 / 2] & 1)) + Pico32x.sh2irqi[0] |= P32XI_CMD; + else + Pico32x.sh2irqi[0] &= ~P32XI_CMD; + + if ((Pico32x.sh2irq_mask[1] & 2) && (Pico32x.regs[2 / 2] & 2)) + Pico32x.sh2irqi[1] |= P32XI_CMD; + else + Pico32x.sh2irqi[1] &= ~P32XI_CMD; + + p32x_update_irls(sh2, m68k_cycles); +} + +void Pico32xStartup(void) +{ + elprintf(EL_STATUS|EL_32X, "32X startup"); + + // TODO: OOM handling + PicoAHW |= PAHW_32X; + sh2_init(&msh2, 0, &ssh2); + msh2.irq_callback = sh2_irq_cb; + sh2_init(&ssh2, 1, &msh2); + ssh2.irq_callback = sh2_irq_cb; + + PicoMemSetup32x(); + p32x_pwm_ctl_changed(); + p32x_timers_recalc(); + + Pico32x.sh2_regs[0] = P32XS2_ADEN; + if (Pico.m.ncart_in) + Pico32x.sh2_regs[0] |= P32XS_nCART; + + if (!Pico.m.pal) + Pico32x.vdp_regs[0] |= P32XV_nPAL; + + rendstatus_old = -1; + + emu_32x_startup(); +} + +#define HWSWAP(x) (((x) << 16) | ((x) >> 16)) +void p32x_reset_sh2s(void) +{ + elprintf(EL_32X, "sh2 reset"); + + sh2_reset(&msh2); + sh2_reset(&ssh2); + sh2_peripheral_reset(&msh2); + sh2_peripheral_reset(&ssh2); + + // if we don't have BIOS set, perform it's work here. + // MSH2 + if (p32x_bios_m == NULL) { + unsigned int idl_src, idl_dst, idl_size; // initial data load + unsigned int vbr; + + // initial data + idl_src = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d4)) & ~0xf0000000; + idl_dst = HWSWAP(*(unsigned int *)(Pico.rom + 0x3d8)) & ~0xf0000000; + idl_size= HWSWAP(*(unsigned int *)(Pico.rom + 0x3dc)); + if (idl_size > Pico.romsize || idl_src + idl_size > Pico.romsize || + idl_size > 0x40000 || idl_dst + idl_size > 0x40000 || (idl_src & 3) || (idl_dst & 3)) { + elprintf(EL_STATUS|EL_ANOMALY, "32x: invalid initial data ptrs: %06x -> %06x, %06x", + idl_src, idl_dst, idl_size); + } + else + memcpy(Pico32xMem->sdram + idl_dst, Pico.rom + idl_src, idl_size); + + // GBR/VBR + vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3e8)); + sh2_set_gbr(0, 0x20004000); + sh2_set_vbr(0, vbr); + + // checksum and M_OK + Pico32x.regs[0x28 / 2] = *(unsigned short *)(Pico.rom + 0x18e); + // program will set M_OK + } + + // SSH2 + if (p32x_bios_s == NULL) { + unsigned int vbr; + + // GBR/VBR + vbr = HWSWAP(*(unsigned int *)(Pico.rom + 0x3ec)); + sh2_set_gbr(1, 0x20004000); + sh2_set_vbr(1, vbr); + // program will set S_OK + } + + msh2.m68krcycles_done = ssh2.m68krcycles_done = SekCyclesDone(); +} + +void Pico32xInit(void) +{ + if (msh2.mult_m68k_to_sh2 == 0 || msh2.mult_sh2_to_m68k == 0) + Pico32xSetClocks(PICO_MSH2_HZ, 0); + if (ssh2.mult_m68k_to_sh2 == 0 || ssh2.mult_sh2_to_m68k == 0) + Pico32xSetClocks(0, PICO_MSH2_HZ); +} + +void PicoPower32x(void) +{ + memset(&Pico32x, 0, sizeof(Pico32x)); + + Pico32x.regs[0] = P32XS_REN|P32XS_nRES; // verified + Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_PEN; +} + +void PicoReset32x(void) +{ + if (PicoAHW & PAHW_32X) { + p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VRES); + p32x_sh2_poll_event(&msh2, SH2_IDLE_STATES, 0); + p32x_sh2_poll_event(&ssh2, SH2_IDLE_STATES, 0); + p32x_pwm_ctl_changed(); + p32x_timers_recalc(); + } +} + +static void p32x_start_blank(void) +{ + if (Pico32xDrawMode != PDM32X_OFF && !PicoSkipFrame) { + int offs, lines; + + pprof_start(draw); + + offs = 8; lines = 224; + if ((Pico.video.reg[1] & 8) && !(PicoOpt & POPT_ALT_RENDERER)) { + offs = 0; + lines = 240; + } + + // XXX: no proper handling of 32col mode.. + if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0 && // 32x not blanking + (Pico.video.reg[12] & 1) && // 40col mode + (PicoDrawMask & PDRAW_32X_ON)) + { + int md_bg = Pico.video.reg[7] & 0x3f; + + // we draw full layer (not line-by-line) + PicoDraw32xLayer(offs, lines, md_bg); + } + else if (Pico32xDrawMode != PDM32X_32X_ONLY) + PicoDraw32xLayerMdOnly(offs, lines); + + pprof_end(draw); + } + + // enter vblank + Pico32x.vdp_regs[0x0a/2] |= P32XV_VBLK|P32XV_PEN; + + // FB swap waits until vblank + if ((Pico32x.vdp_regs[0x0a/2] ^ Pico32x.pending_fb) & P32XV_FS) { + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_FS; + Pico32x.vdp_regs[0x0a/2] |= Pico32x.pending_fb; + Pico32xSwapDRAM(Pico32x.pending_fb ^ 1); + } + + p32x_trigger_irq(NULL, SekCyclesDone(), P32XI_VINT); + p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); + p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); +} + +void p32x_schedule_hint(SH2 *sh2, int m68k_cycles) +{ + // rather rough, 32x hint is useless in practice + int after; + + if (!((Pico32x.sh2irq_mask[0] | Pico32x.sh2irq_mask[1]) & 4)) + return; // nobody cares + // note: when Pico.m.scanline is 224, SH2s might + // still be at scanline 93 (or so) + if (!(Pico32x.sh2_regs[0] & 0x80) && Pico.m.scanline > 224) + return; + + after = (Pico32x.sh2_regs[4 / 2] + 1) * 488; + if (sh2 != NULL) + p32x_event_schedule_sh2(sh2, P32X_EVENT_HINT, after); + else + p32x_event_schedule(m68k_cycles, P32X_EVENT_HINT, after); +} + +/* events */ +static void fillend_event(unsigned int now) +{ + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_nFEN; + p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, now); + p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, now); +} + +static void hint_event(unsigned int now) +{ + p32x_trigger_irq(NULL, now, P32XI_HINT); + p32x_schedule_hint(NULL, now); +} + +typedef void (event_cb)(unsigned int now); + +/* times are in m68k (7.6MHz) cycles */ +unsigned int p32x_event_times[P32X_EVENT_COUNT]; +static unsigned int event_time_next; +static event_cb *p32x_event_cbs[P32X_EVENT_COUNT] = { + [P32X_EVENT_PWM] = p32x_pwm_irq_event, + [P32X_EVENT_FILLEND] = fillend_event, + [P32X_EVENT_HINT] = hint_event, +}; + +// schedule event at some time 'after', in m68k clocks +void p32x_event_schedule(unsigned int now, enum p32x_event event, int after) +{ + unsigned int when; + + when = (now + after) | 1; + + elprintf(EL_32X, "32x: new event #%u %u->%u", event, now, when); + p32x_event_times[event] = when; + + if (event_time_next == 0 || CYCLES_GT(event_time_next, when)) + event_time_next = when; +} + +void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after) +{ + unsigned int now = sh2_cycles_done_m68k(sh2); + int left_to_next; + + p32x_event_schedule(now, event, after); + + left_to_next = (event_time_next - now) * 3; + sh2_end_run(sh2, left_to_next); +} + +static void p32x_run_events(unsigned int until) +{ + int oldest, oldest_diff, time; + int i, diff; + + while (1) { + oldest = -1, oldest_diff = 0x7fffffff; + + for (i = 0; i < P32X_EVENT_COUNT; i++) { + if (p32x_event_times[i]) { + diff = p32x_event_times[i] - until; + if (diff < oldest_diff) { + oldest_diff = diff; + oldest = i; + } + } + } + + if (oldest_diff <= 0) { + time = p32x_event_times[oldest]; + p32x_event_times[oldest] = 0; + elprintf(EL_32X, "32x: run event #%d %u", oldest, time); + p32x_event_cbs[oldest](time); + } + else if (oldest_diff < 0x7fffffff) { + event_time_next = p32x_event_times[oldest]; + break; + } + else { + event_time_next = 0; + break; + } + } + + if (oldest != -1) + elprintf(EL_32X, "32x: next event #%d at %u", + oldest, event_time_next); +} + +static inline void run_sh2(SH2 *sh2, int m68k_cycles) +{ + int cycles, done; + + pevt_log_sh2_o(sh2, EVT_RUN_START); + sh2->state |= SH2_STATE_RUN; + cycles = C_M68K_TO_SH2(*sh2, m68k_cycles); + elprintf_sh2(sh2, EL_32X, "+run %u %d @%08x", + sh2->m68krcycles_done, cycles, sh2->pc); + + done = sh2_execute(sh2, cycles, PicoOpt & POPT_EN_DRC); + + sh2->m68krcycles_done += C_SH2_TO_M68K(*sh2, done); + sh2->state &= ~SH2_STATE_RUN; + pevt_log_sh2_o(sh2, EVT_RUN_END); + elprintf_sh2(sh2, EL_32X, "-run %u %d", + sh2->m68krcycles_done, done); +} + +// sync other sh2 to this one +// note: recursive call +void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target) +{ + SH2 *osh2 = sh2->other_sh2; + int left_to_event; + int m68k_cycles; + + if (osh2->state & SH2_STATE_RUN) + return; + + m68k_cycles = m68k_target - osh2->m68krcycles_done; + if (m68k_cycles < 200) + return; + + if (osh2->state & SH2_IDLE_STATES) { + osh2->m68krcycles_done = m68k_target; + return; + } + + elprintf_sh2(osh2, EL_32X, "sync to %u %d", + m68k_target, m68k_cycles); + + run_sh2(osh2, m68k_cycles); + + // there might be new event to schedule current sh2 to + if (event_time_next) { + left_to_event = event_time_next - m68k_target; + left_to_event *= 3; + if (sh2_cycles_left(sh2) > left_to_event) { + if (left_to_event < 1) + left_to_event = 1; + sh2_end_run(sh2, left_to_event); + } + } +} + +#define sync_sh2s_normal p32x_sync_sh2s +//#define sync_sh2s_lockstep p32x_sync_sh2s + +/* most timing is in 68k clock */ +void sync_sh2s_normal(unsigned int m68k_target) +{ + unsigned int now, target, timer_cycles; + int cycles; + + elprintf(EL_32X, "sh2 sync to %u", m68k_target); + + if (!(Pico32x.regs[0] & P32XS_nRES)) { + msh2.m68krcycles_done = ssh2.m68krcycles_done = m68k_target; + return; // rare + } + + now = msh2.m68krcycles_done; + if (CYCLES_GT(now, ssh2.m68krcycles_done)) + now = ssh2.m68krcycles_done; + timer_cycles = now; + + while (CYCLES_GT(m68k_target, now)) + { + if (event_time_next && CYCLES_GE(now, event_time_next)) + p32x_run_events(now); + + target = m68k_target; + if (event_time_next && CYCLES_GT(target, event_time_next)) + target = event_time_next; + + while (CYCLES_GT(target, now)) + { + elprintf(EL_32X, "sh2 exec to %u %d,%d/%d, flags %x", target, + target - msh2.m68krcycles_done, target - ssh2.m68krcycles_done, + m68k_target - now, Pico32x.emu_flags); + + if (!(ssh2.state & SH2_IDLE_STATES)) { + cycles = target - ssh2.m68krcycles_done; + if (cycles > 0) { + run_sh2(&ssh2, cycles); + + if (event_time_next && CYCLES_GT(target, event_time_next)) + target = event_time_next; + } + } + + if (!(msh2.state & SH2_IDLE_STATES)) { + cycles = target - msh2.m68krcycles_done; + if (cycles > 0) { + run_sh2(&msh2, cycles); + + if (event_time_next && CYCLES_GT(target, event_time_next)) + target = event_time_next; + } + } + + now = target; + if (!(msh2.state & SH2_IDLE_STATES)) { + if (CYCLES_GT(now, msh2.m68krcycles_done)) + now = msh2.m68krcycles_done; + } + if (!(ssh2.state & SH2_IDLE_STATES)) { + if (CYCLES_GT(now, ssh2.m68krcycles_done)) + now = ssh2.m68krcycles_done; + } + } + + p32x_timers_do(now - timer_cycles); + timer_cycles = now; + } + + // advance idle CPUs + if (msh2.state & SH2_IDLE_STATES) { + if (CYCLES_GT(m68k_target, msh2.m68krcycles_done)) + msh2.m68krcycles_done = m68k_target; + } + if (ssh2.state & SH2_IDLE_STATES) { + if (CYCLES_GT(m68k_target, ssh2.m68krcycles_done)) + ssh2.m68krcycles_done = m68k_target; + } +} + +#define STEP_68K 24 + +void sync_sh2s_lockstep(unsigned int m68k_target) +{ + unsigned int mcycles; + + mcycles = msh2.m68krcycles_done; + if (ssh2.m68krcycles_done < mcycles) + mcycles = ssh2.m68krcycles_done; + + while (mcycles < m68k_target) { + mcycles += STEP_68K; + sync_sh2s_normal(mcycles); + } +} + +#define CPUS_RUN(m68k_cycles) do { \ + if (PicoAHW & PAHW_MCD) \ + pcd_run_cpus(m68k_cycles); \ + else \ + SekRunM68k(m68k_cycles); \ + \ + if ((Pico32x.emu_flags & P32XF_Z80_32X_IO) && Pico.m.z80Run \ + && !Pico.m.z80_reset && (PicoOpt & POPT_EN_Z80)) \ + PicoSyncZ80(SekCyclesDone()); \ + if (Pico32x.emu_flags & (P32XF_68KCPOLL|P32XF_68KVPOLL)) \ + p32x_sync_sh2s(SekCyclesDone()); \ +} while (0) + +#define PICO_32X +#define PICO_CD +#include "../pico_cmn.inc" + +void PicoFrame32x(void) +{ + Pico.m.scanline = 0; + + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_VBLK; // get out of vblank + if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0) // no forced blanking + Pico32x.vdp_regs[0x0a/2] &= ~P32XV_PEN; // no palette access + + if (!(Pico32x.sh2_regs[0] & 0x80)) + p32x_schedule_hint(NULL, SekCyclesDone()); + p32x_sh2_poll_event(&msh2, SH2_STATE_VPOLL, 0); + p32x_sh2_poll_event(&ssh2, SH2_STATE_VPOLL, 0); + + if (PicoAHW & PAHW_MCD) + pcd_prepare_frame(); + + PicoFrameStart(); + PicoFrameHints(); + + elprintf(EL_32X, "poll: %02x %02x %02x", + Pico32x.emu_flags & 3, msh2.state, ssh2.state); +} + +// calculate multipliers against 68k clock (7670442) +// normally * 3, but effectively slower due to high latencies everywhere +// however using something lower breaks MK2 animations +void Pico32xSetClocks(int msh2_hz, int ssh2_hz) +{ + float m68k_clk = (float)(OSC_NTSC / 7); + if (msh2_hz > 0) { + msh2.mult_m68k_to_sh2 = (int)((float)msh2_hz * (1 << CYCLE_MULT_SHIFT) / m68k_clk); + msh2.mult_sh2_to_m68k = (int)(m68k_clk * (1 << CYCLE_MULT_SHIFT) / (float)msh2_hz); + } + if (ssh2_hz > 0) { + ssh2.mult_m68k_to_sh2 = (int)((float)ssh2_hz * (1 << CYCLE_MULT_SHIFT) / m68k_clk); + ssh2.mult_sh2_to_m68k = (int)(m68k_clk * (1 << CYCLE_MULT_SHIFT) / (float)ssh2_hz); + } +} diff --git a/waterbox/picodrive/pico/32x/draw.c b/waterbox/picodrive/pico/32x/draw.c new file mode 100644 index 0000000000..66f67a7e4a --- /dev/null +++ b/waterbox/picodrive/pico/32x/draw.c @@ -0,0 +1,329 @@ +/* + * PicoDrive + * (C) notaz, 2009,2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include "../pico_int.h" + +int (*PicoScan32xBegin)(unsigned int num); +int (*PicoScan32xEnd)(unsigned int num); +int Pico32xDrawMode; + +static void convert_pal555(int invert_prio) +{ + unsigned int *ps = (void *)Pico32xMem->pal; + unsigned int *pd = (void *)Pico32xMem->pal_native; + unsigned int m1 = 0x001f001f; + unsigned int m2 = 0x03e003e0; + unsigned int m3 = 0xfc00fc00; + unsigned int inv = 0; + int i; + + if (invert_prio) + inv = 0x00200020; + + // place prio to LS green bit + for (i = 0x100/2; i > 0; i--, ps++, pd++) { + unsigned int t = *ps; + *pd = (((t & m1) << 11) | ((t & m2) << 1) | ((t & m3) >> 10)) ^ inv; + } + + Pico32x.dirty_pal = 0; +} + +// direct color mode +#define do_line_dc(pd, p32x, pmd, inv, pmd_draw_code) \ +{ \ + const unsigned int m1 = 0x001f; \ + const unsigned int m2 = 0x03e0; \ + const unsigned int m3 = 0x7c00; \ + int i; \ + \ + for (i = 320; i > 0; i--, pd++, p32x++, pmd++) { \ + unsigned short t = *p32x; \ + if ((*pmd & 0x3f) != mdbg && !((t ^ inv) & 0x8000)) { \ + pmd_draw_code; \ + continue; \ + } \ + \ + *pd = ((t & m1) << 11) | ((t & m2) << 1) | ((t & m3) >> 10); \ + } \ +} + +// packed pixel mode +#define do_line_pp(pd, p32x, pmd, pmd_draw_code) \ +{ \ + unsigned short t; \ + int i; \ + for (i = 320; i > 0; i--, pd++, p32x++, pmd++) { \ + t = pal[*(unsigned char *)((long)p32x ^ 1)]; \ + if ((t & 0x20) || (*pmd & 0x3f) == mdbg) \ + *pd = t; \ + else \ + pmd_draw_code; \ + } \ +} + +// run length mode +#define do_line_rl(pd, p32x, pmd, pmd_draw_code) \ +{ \ + unsigned short len, t; \ + int i; \ + for (i = 320; i > 0; p32x++) { \ + t = pal[*p32x & 0xff]; \ + for (len = (*p32x >> 8) + 1; len > 0 && i > 0; len--, i--, pd++, pmd++) { \ + if ((*pmd & 0x3f) == mdbg || (t & 0x20)) \ + *pd = t; \ + else \ + pmd_draw_code; \ + } \ + } \ +} + +// this is almost never used (Wiz and menu bg gen only) +void FinalizeLine32xRGB555(int sh, int line) +{ + unsigned short *pd = DrawLineDest; + unsigned short *pal = Pico32xMem->pal_native; + unsigned char *pmd = HighCol + 8; + unsigned short *dram, *p32x; + unsigned char mdbg; + + FinalizeLine555(sh, line); + + if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 0 || // 32x blanking + // XXX: how is 32col mode hadled by real hardware? + !(Pico.video.reg[12] & 1) || // 32col mode + !(PicoDrawMask & PDRAW_32X_ON)) + { + return; + } + + dram = (void *)Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS]; + p32x = dram + dram[line]; + mdbg = Pico.video.reg[7] & 0x3f; + + if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2) { // Direct Color Mode + int inv_bit = (Pico32x.vdp_regs[0] & P32XV_PRI) ? 0x8000 : 0; + do_line_dc(pd, p32x, pmd, inv_bit,); + return; + } + + if (Pico32x.dirty_pal) + convert_pal555(Pico32x.vdp_regs[0] & P32XV_PRI); + + if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 1) { // Packed Pixel Mode + unsigned char *p32xb = (void *)p32x; + if (Pico32x.vdp_regs[2 / 2] & P32XV_SFT) + p32xb++; + do_line_pp(pd, p32xb, pmd,); + } + else { // Run Length Mode + do_line_rl(pd, p32x, pmd,); + } +} + +#define MD_LAYER_CODE \ + *dst = palmd[*pmd] + +#define PICOSCAN_PRE \ + PicoScan32xBegin(l + (lines_sft_offs & 0xff)); \ + dst = DrawLineDest; \ + +#define PICOSCAN_POST \ + PicoScan32xEnd(l + (lines_sft_offs & 0xff)); \ + +#define make_do_loop(name, pre_code, post_code, md_code) \ +/* Direct Color Mode */ \ +static void do_loop_dc##name(unsigned short *dst, \ + unsigned short *dram, int lines_sft_offs, int mdbg) \ +{ \ + int inv_bit = (Pico32x.vdp_regs[0] & P32XV_PRI) ? 0x8000 : 0; \ + unsigned char *pmd = PicoDraw2FB + \ + 328 * (lines_sft_offs & 0xff) + 8; \ + unsigned short *palmd = HighPal; \ + unsigned short *p32x; \ + int lines = lines_sft_offs >> 16; \ + int l; \ + (void)palmd; \ + for (l = 0; l < lines; l++, pmd += 8) { \ + pre_code; \ + p32x = dram + dram[l]; \ + do_line_dc(dst, p32x, pmd, inv_bit, md_code); \ + post_code; \ + } \ +} \ + \ +/* Packed Pixel Mode */ \ +static void do_loop_pp##name(unsigned short *dst, \ + unsigned short *dram, int lines_sft_offs, int mdbg) \ +{ \ + unsigned short *pal = Pico32xMem->pal_native; \ + unsigned char *pmd = PicoDraw2FB + \ + 328 * (lines_sft_offs & 0xff) + 8; \ + unsigned short *palmd = HighPal; \ + unsigned char *p32x; \ + int lines = lines_sft_offs >> 16; \ + int l; \ + (void)palmd; \ + for (l = 0; l < lines; l++, pmd += 8) { \ + pre_code; \ + p32x = (void *)(dram + dram[l]); \ + p32x += (lines_sft_offs >> 8) & 1; \ + do_line_pp(dst, p32x, pmd, md_code); \ + post_code; \ + } \ +} \ + \ +/* Run Length Mode */ \ +static void do_loop_rl##name(unsigned short *dst, \ + unsigned short *dram, int lines_sft_offs, int mdbg) \ +{ \ + unsigned short *pal = Pico32xMem->pal_native; \ + unsigned char *pmd = PicoDraw2FB + \ + 328 * (lines_sft_offs & 0xff) + 8; \ + unsigned short *palmd = HighPal; \ + unsigned short *p32x; \ + int lines = lines_sft_offs >> 16; \ + int l; \ + (void)palmd; \ + for (l = 0; l < lines; l++, pmd += 8) { \ + pre_code; \ + p32x = dram + dram[l]; \ + do_line_rl(dst, p32x, pmd, md_code); \ + post_code; \ + } \ +} + +#ifdef _ASM_32X_DRAW +#undef make_do_loop +#define make_do_loop(name, pre_code, post_code, md_code) \ +extern void do_loop_dc##name(unsigned short *dst, \ + unsigned short *dram, int lines_offs, int mdbg); \ +extern void do_loop_pp##name(unsigned short *dst, \ + unsigned short *dram, int lines_offs, int mdbg); \ +extern void do_loop_rl##name(unsigned short *dst, \ + unsigned short *dram, int lines_offs, int mdbg); +#endif + +make_do_loop(,,,) +make_do_loop(_md, , , MD_LAYER_CODE) +make_do_loop(_scan, PICOSCAN_PRE, PICOSCAN_POST, ) +make_do_loop(_scan_md, PICOSCAN_PRE, PICOSCAN_POST, MD_LAYER_CODE) + +typedef void (*do_loop_func)(unsigned short *dst, unsigned short *dram, int lines, int mdbg); +enum { DO_LOOP, DO_LOOP_MD, DO_LOOP_SCAN, DO_LOOP_MD_SCAN }; + +static const do_loop_func do_loop_dc_f[] = { do_loop_dc, do_loop_dc_md, do_loop_dc_scan, do_loop_dc_scan_md }; +static const do_loop_func do_loop_pp_f[] = { do_loop_pp, do_loop_pp_md, do_loop_pp_scan, do_loop_pp_scan_md }; +static const do_loop_func do_loop_rl_f[] = { do_loop_rl, do_loop_rl_md, do_loop_rl_scan, do_loop_rl_scan_md }; + +void PicoDraw32xLayer(int offs, int lines, int md_bg) +{ + int have_scan = PicoScan32xBegin != NULL && PicoScan32xEnd != NULL; + const do_loop_func *do_loop; + unsigned short *dram; + int lines_sft_offs; + int which_func; + + DrawLineDest = (char *)DrawLineDestBase + offs * DrawLineDestIncrement; + dram = Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS]; + + if (Pico32xDrawMode == PDM32X_BOTH) { + if (Pico.m.dirtyPal) + PicoDrawUpdateHighPal(); + } + + if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2) + { + // Direct Color Mode + do_loop = do_loop_dc_f; + goto do_it; + } + + if (Pico32x.dirty_pal) + convert_pal555(Pico32x.vdp_regs[0] & P32XV_PRI); + + if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 1) + { + // Packed Pixel Mode + do_loop = do_loop_pp_f; + } + else + { + // Run Length Mode + do_loop = do_loop_rl_f; + } + +do_it: + if (Pico32xDrawMode == PDM32X_BOTH) + which_func = have_scan ? DO_LOOP_MD_SCAN : DO_LOOP_MD; + else + which_func = have_scan ? DO_LOOP_SCAN : DO_LOOP; + lines_sft_offs = (lines << 16) | offs; + if (Pico32x.vdp_regs[2 / 2] & P32XV_SFT) + lines_sft_offs |= 1 << 8; + + do_loop[which_func](DrawLineDest, dram, lines_sft_offs, md_bg); +} + +// mostly unused, games tend to keep 32X layer on +void PicoDraw32xLayerMdOnly(int offs, int lines) +{ + int have_scan = PicoScan32xBegin != NULL && PicoScan32xEnd != NULL; + unsigned short *dst = (void *)((char *)DrawLineDestBase + offs * DrawLineDestIncrement); + unsigned char *pmd = PicoDraw2FB + 328 * offs + 8; + unsigned short *pal = HighPal; + int poffs = 0, plen = 320; + int l, p; + + if (!(Pico.video.reg[12] & 1)) { + // 32col mode + poffs = 32; + plen = 256; + } + + if (Pico.m.dirtyPal) + PicoDrawUpdateHighPal(); + + dst += poffs; + for (l = 0; l < lines; l++) { + if (have_scan) { + PicoScan32xBegin(l + offs); + dst = DrawLineDest + poffs; + } + for (p = 0; p < plen; p += 4) { + dst[p + 0] = pal[*pmd++]; + dst[p + 1] = pal[*pmd++]; + dst[p + 2] = pal[*pmd++]; + dst[p + 3] = pal[*pmd++]; + } + dst = (void *)((char *)dst + DrawLineDestIncrement); + pmd += 328 - plen; + if (have_scan) + PicoScan32xEnd(l + offs); + } +} + +void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode) +{ +#ifdef _ASM_32X_DRAW + extern void *Pico32xNativePal; + Pico32xNativePal = Pico32xMem->pal_native; +#endif + + if (which == PDF_RGB555 && use_32x_line_mode) { + // we'll draw via FinalizeLine32xRGB555 (rare) + PicoDrawSetInternalBuf(NULL, 0); + Pico32xDrawMode = PDM32X_OFF; + return; + } + + // use the same layout as alt renderer + PicoDrawSetInternalBuf(PicoDraw2FB, 328); + Pico32xDrawMode = (which == PDF_RGB555) ? PDM32X_32X_ONLY : PDM32X_BOTH; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/32x/memory.c b/waterbox/picodrive/pico/32x/memory.c new file mode 100644 index 0000000000..d2541c4b56 --- /dev/null +++ b/waterbox/picodrive/pico/32x/memory.c @@ -0,0 +1,1863 @@ +/* + * PicoDrive + * (C) notaz, 2009,2010,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + * + * Register map: + * a15100 F....... R.....EA F.....AC N...VHMP 4000 // Fm Ren nrEs Aden Cart heN V H cMd Pwm + * a15102 ........ ......SM ? 4002 // intS intM + * a15104 ........ ......10 ........ hhhhhhhh 4004 // bk1 bk0 Hint + * a15106 ........ F....SDR UE...... .....SDR 4006 // Full 68S Dma Rv fUll[fb] Empt[fb] + * a15108 (32bit DREQ src) 4008 + * a1510c (32bit DREQ dst) 400c + * a15110 llllllll llllll00 4010 // DREQ Len + * a15112 (16bit FIFO reg) 4012 + * a15114 0 (16bit VRES clr) 4014 + * a15116 0 (16bit Vint clr) 4016 + * a15118 0 (16bit Hint clr) 4018 + * a1511a .......? .......C (16bit CMD clr) 401a // TV Cm + * a1511c 0 (16bit PWM clr) 401c + * a1511e 0 ? 401e + * a15120 (16 bytes comm) 2020 + * a15130 (PWM) 2030 + * + * SH2 addr lines: + * iii. .cc. ..xx * // Internal, Cs, x + * + * sh2 map, wait/bus cycles (from docs): + * r w + * rom 0000000-0003fff 1 - + * sys reg 0004000-00040ff 1 1 + * vdp reg 0004100-00041ff 5 5 + * vdp pal 0004200-00043ff 5 5 + * cart 2000000-23fffff 6-15 + * dram/fb 4000000-401ffff 5-12 1-3 + * fb ovr 4020000-403ffff + * sdram 6000000-603ffff 12 2 (cycles) + * d.a. c0000000-? + */ +#include "../pico_int.h" +#include "../memory.h" + +static const char str_mars[] = "MARS"; + +void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; +struct Pico32xMem *Pico32xMem; + +static void bank_switch(int b); + +// addressing byte in 16bit reg +#define REG8IN16(ptr, offs) ((u8 *)ptr)[(offs) ^ 1] + +// poll detection +#define POLL_THRESHOLD 3 + +static struct { + u32 addr, cycles; + int cnt; +} m68k_poll; + +static int m68k_poll_detect(u32 a, u32 cycles, u32 flags) +{ + int ret = 0; + + if (a - 2 <= m68k_poll.addr && m68k_poll.addr <= a + 2 + && cycles - m68k_poll.cycles <= 64 && !SekNotPolling) + { + if (m68k_poll.cnt++ > POLL_THRESHOLD) { + if (!(Pico32x.emu_flags & flags)) { + elprintf(EL_32X, "m68k poll addr %08x, cyc %u", + a, cycles - m68k_poll.cycles); + ret = 1; + } + Pico32x.emu_flags |= flags; + } + } + else { + m68k_poll.cnt = 0; + m68k_poll.addr = a; + SekNotPolling = 0; + } + m68k_poll.cycles = cycles; + + return ret; +} + +void p32x_m68k_poll_event(u32 flags) +{ + if (Pico32x.emu_flags & flags) { + elprintf(EL_32X, "m68k poll %02x -> %02x", Pico32x.emu_flags, + Pico32x.emu_flags & ~flags); + Pico32x.emu_flags &= ~flags; + SekSetStop(0); + } + m68k_poll.addr = m68k_poll.cnt = 0; +} + +static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt) +{ + int cycles_left = sh2_cycles_left(sh2); + + if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) { + if (sh2->poll_cnt++ > maxcnt) { + if (!(sh2->state & flags)) + elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", + sh2->state, sh2->state | flags); + + sh2->state |= flags; + sh2_end_run(sh2, 1); + pevt_log_sh2(sh2, EVT_POLL_START); + return; + } + } + else + sh2->poll_cnt = 0; + sh2->poll_addr = a; + sh2->poll_cycles = cycles_left; +} + +void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles) +{ + if (sh2->state & flags) { + elprintf_sh2(sh2, EL_32X, "state: %02x->%02x", sh2->state, + sh2->state & ~flags); + + if (sh2->m68krcycles_done < m68k_cycles) + sh2->m68krcycles_done = m68k_cycles; + + pevt_log_sh2_o(sh2, EVT_POLL_END); + } + + sh2->state &= ~flags; + sh2->poll_addr = sh2->poll_cycles = sh2->poll_cnt = 0; +} + +static void sh2s_sync_on_read(SH2 *sh2) +{ + int cycles; + if (sh2->poll_cnt != 0) + return; + + cycles = sh2_cycles_done(sh2); + if (cycles > 600) + p32x_sync_other_sh2(sh2, sh2->m68krcycles_done + cycles / 3); +} + +// SH2 faking +//#define FAKE_SH2 +#ifdef FAKE_SH2 +static int p32x_csum_faked; +static const u16 comm_fakevals[] = { + 0x4d5f, 0x4f4b, // M_OK + 0x535f, 0x4f4b, // S_OK + 0x4D41, 0x5346, // MASF - Brutal Unleashed + 0x5331, 0x4d31, // Darxide + 0x5332, 0x4d32, + 0x5333, 0x4d33, + 0x0000, 0x0000, // eq for doom + 0x0002, // Mortal Kombat +// 0, // pad +}; + +static u32 sh2_comm_faker(u32 a) +{ + static int f = 0; + if (a == 0x28 && !p32x_csum_faked) { + p32x_csum_faked = 1; + return *(unsigned short *)(Pico.rom + 0x18e); + } + if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0])) + f = 0; + return comm_fakevals[f++]; +} +#endif + +// ------------------------------------------------------------------ +// 68k regs + +static u32 p32x_reg_read16(u32 a) +{ + a &= 0x3e; + +#if 0 + if ((a & 0x30) == 0x20) + return sh2_comm_faker(a); +#else + if ((a & 0x30) == 0x20) { + unsigned int cycles = SekCyclesDone(); + int comreg = 1 << (a & 0x0f) / 2; + + if (cycles - msh2.m68krcycles_done > 244 + || (Pico32x.comm_dirty_68k & comreg)) + p32x_sync_sh2s(cycles); + + if (Pico32x.comm_dirty_sh2 & comreg) + Pico32x.comm_dirty_sh2 &= ~comreg; + else if (m68k_poll_detect(a, cycles, P32XF_68KCPOLL)) { + SekSetStop(1); + SekEndRun(16); + } + goto out; + } +#endif + + if (a == 2) { // INTM, INTS + unsigned int cycles = SekCyclesDone(); + if (cycles - msh2.m68krcycles_done > 64) + p32x_sync_sh2s(cycles); + goto out; + } + + if ((a & 0x30) == 0x30) + return p32x_pwm_read16(a, NULL, SekCyclesDone()); + +out: + return Pico32x.regs[a / 2]; +} + +static void dreq0_write(u16 *r, u32 d) +{ + if (!(r[6 / 2] & P32XS_68S)) { + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO w16 without 68S?"); + return; // ignored - tested + } + if (Pico32x.dmac0_fifo_ptr < DMAC_FIFO_LEN) { + Pico32x.dmac_fifo[Pico32x.dmac0_fifo_ptr++] = d; + if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN) + r[6 / 2] |= P32XS_FULL; + // tested: len register decrements and 68S clears + // even if SH2s/DMAC aren't active.. + r[0x10 / 2]--; + if (r[0x10 / 2] == 0) + r[6 / 2] &= ~P32XS_68S; + + if ((Pico32x.dmac0_fifo_ptr & 3) == 0) { + p32x_sync_sh2s(SekCyclesDone()); + p32x_dreq0_trigger(); + } + } + else + elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!"); +} + +// writable bits tested +static void p32x_reg_write8(u32 a, u32 d) +{ + u16 *r = Pico32x.regs; + a &= 0x3f; + + // for things like bset on comm port + m68k_poll.cnt = 0; + + switch (a) { + case 0x00: // adapter ctl: FM writable + REG8IN16(r, 0x00) = d & 0x80; + return; + case 0x01: // adapter ctl: RES and ADEN writable + if ((d ^ r[0]) & d & P32XS_nRES) + p32x_reset_sh2s(); + REG8IN16(r, 0x01) &= ~(P32XS_nRES|P32XS_ADEN); + REG8IN16(r, 0x01) |= d & (P32XS_nRES|P32XS_ADEN); + return; + case 0x02: // ignored, always 0 + return; + case 0x03: // irq ctl + if ((d ^ r[0x02 / 2]) & 3) { + int cycles = SekCyclesDone(); + p32x_sync_sh2s(cycles); + r[0x02 / 2] = d & 3; + p32x_update_cmd_irq(NULL, cycles); + } + return; + case 0x04: // ignored, always 0 + return; + case 0x05: // bank + d &= 3; + if (r[0x04 / 2] != d) { + r[0x04 / 2] = d; + bank_switch(d); + } + return; + case 0x06: // ignored, always 0 + return; + case 0x07: // DREQ ctl + REG8IN16(r, 0x07) &= ~(P32XS_68S|P32XS_DMA|P32XS_RV); + if (!(d & P32XS_68S)) { + Pico32x.dmac0_fifo_ptr = 0; + REG8IN16(r, 0x07) &= ~P32XS_FULL; + } + REG8IN16(r, 0x07) |= d & (P32XS_68S|P32XS_DMA|P32XS_RV); + return; + case 0x08: // ignored, always 0 + return; + case 0x09: // DREQ src + REG8IN16(r, 0x09) = d; + return; + case 0x0a: + REG8IN16(r, 0x0a) = d; + return; + case 0x0b: + REG8IN16(r, 0x0b) = d & 0xfe; + return; + case 0x0c: // ignored, always 0 + return; + case 0x0d: // DREQ dest + case 0x0e: + case 0x0f: + case 0x10: // DREQ len + REG8IN16(r, a) = d; + return; + case 0x11: + REG8IN16(r, a) = d & 0xfc; + return; + // DREQ FIFO - writes to odd addr go to fifo + // do writes to even work? Reads return 0 + case 0x12: + REG8IN16(r, a) = d; + return; + case 0x13: + d = (REG8IN16(r, 0x12) << 8) | (d & 0xff); + REG8IN16(r, 0x12) = 0; + dreq0_write(r, d); + return; + case 0x14: // ignored, always 0 + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + return; + case 0x1a: // what's this? + elprintf(EL_32X|EL_ANOMALY, "mystery w8 %02x %02x", a, d); + REG8IN16(r, a) = d & 0x01; + return; + case 0x1b: // TV + REG8IN16(r, a) = d & 0x01; + return; + case 0x1c: // ignored, always 0 + case 0x1d: + case 0x1e: + case 0x1f: + case 0x30: + return; + case 0x31: // PWM control + REG8IN16(r, a) &= ~0x0f; + REG8IN16(r, a) |= d & 0x0f; + d = r[0x30 / 2]; + goto pwm_write; + case 0x32: // PWM cycle + REG8IN16(r, a) = d & 0x0f; + d = r[0x32 / 2]; + goto pwm_write; + case 0x33: + REG8IN16(r, a) = d; + d = r[0x32 / 2]; + goto pwm_write; + // PWM pulse regs.. Only writes to odd address send a value + // to FIFO; reads are 0 (except status bits) + case 0x34: + case 0x36: + case 0x38: + REG8IN16(r, a) = d; + return; + case 0x35: + case 0x37: + case 0x39: + d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff); + REG8IN16(r, a ^ 1) = 0; + goto pwm_write; + case 0x3a: // ignored, always 0 + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + return; + pwm_write: + p32x_pwm_write16(a & ~1, d, NULL, SekCyclesDone()); + return; + } + + if ((a & 0x30) == 0x20) { + int cycles = SekCyclesDone(); + int comreg; + + if (REG8IN16(r, a) == d) + return; + + comreg = 1 << (a & 0x0f) / 2; + if (Pico32x.comm_dirty_68k & comreg) + p32x_sync_sh2s(cycles); + + REG8IN16(r, a) = d; + p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); + Pico32x.comm_dirty_68k |= comreg; + + if (cycles - (int)msh2.m68krcycles_done > 120) + p32x_sync_sh2s(cycles); + return; + } +} + +static void p32x_reg_write16(u32 a, u32 d) +{ + u16 *r = Pico32x.regs; + a &= 0x3e; + + // for things like bset on comm port + m68k_poll.cnt = 0; + + switch (a) { + case 0x00: // adapter ctl + if ((d ^ r[0]) & d & P32XS_nRES) + p32x_reset_sh2s(); + r[0] &= ~(P32XS_FM|P32XS_nRES|P32XS_ADEN); + r[0] |= d & (P32XS_FM|P32XS_nRES|P32XS_ADEN); + return; + case 0x08: // DREQ src + r[a / 2] = d & 0xff; + return; + case 0x0a: + r[a / 2] = d & ~1; + return; + case 0x0c: // DREQ dest + r[a / 2] = d & 0xff; + return; + case 0x0e: + r[a / 2] = d; + return; + case 0x10: // DREQ len + r[a / 2] = d & ~3; + return; + case 0x12: // FIFO reg + dreq0_write(r, d); + return; + case 0x1a: // TV + mystery bit + r[a / 2] = d & 0x0101; + return; + case 0x30: // PWM control + d = (r[a / 2] & ~0x0f) | (d & 0x0f); + r[a / 2] = d; + p32x_pwm_write16(a, d, NULL, SekCyclesDone()); + return; + } + + // comm port + if ((a & 0x30) == 0x20) { + int cycles = SekCyclesDone(); + int comreg; + + if (r[a / 2] == d) + return; + + comreg = 1 << (a & 0x0f) / 2; + if (Pico32x.comm_dirty_68k & comreg) + p32x_sync_sh2s(cycles); + + r[a / 2] = d; + p32x_sh2_poll_event(&sh2s[0], SH2_STATE_CPOLL, cycles); + p32x_sh2_poll_event(&sh2s[1], SH2_STATE_CPOLL, cycles); + Pico32x.comm_dirty_68k |= comreg; + + if (cycles - (int)msh2.m68krcycles_done > 120) + p32x_sync_sh2s(cycles); + return; + } + // PWM + else if ((a & 0x30) == 0x30) { + p32x_pwm_write16(a, d, NULL, SekCyclesDone()); + return; + } + + p32x_reg_write8(a + 1, d); +} + +// ------------------------------------------------------------------ +// VDP regs +static u32 p32x_vdp_read16(u32 a) +{ + u32 d; + a &= 0x0e; + + d = Pico32x.vdp_regs[a / 2]; + if (a == 0x0a) { + // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0, + // most often at 0xb1-0xb5, even during vblank, + // what's the deal with that? + // we'll just fake it along with hblank for now + Pico32x.vdp_fbcr_fake++; + if (Pico32x.vdp_fbcr_fake & 4) + d |= P32XV_HBLK; + if ((Pico32x.vdp_fbcr_fake & 7) == 0) + d |= P32XV_nFEN; + } + return d; +} + +static void p32x_vdp_write8(u32 a, u32 d) +{ + u16 *r = Pico32x.vdp_regs; + a &= 0x0f; + + // TODO: verify what's writeable + switch (a) { + case 0x01: + // priority inversion is handled in palette + if ((r[0] ^ d) & P32XV_PRI) + Pico32x.dirty_pal = 1; + r[0] = (r[0] & P32XV_nPAL) | (d & 0xff); + break; + case 0x03: // shift (for pp mode) + r[2 / 2] = d & 1; + break; + case 0x05: // fill len + r[4 / 2] = d & 0xff; + break; + case 0x0b: + d &= 1; + Pico32x.pending_fb = d; + // if we are blanking and FS bit is changing + if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) { + r[0x0a/2] ^= P32XV_FS; + Pico32xSwapDRAM(d ^ 1); + elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS); + } + break; + } +} + +static void p32x_vdp_write16(u32 a, u32 d, SH2 *sh2) +{ + a &= 0x0e; + if (a == 6) { // fill start + Pico32x.vdp_regs[6 / 2] = d; + return; + } + if (a == 8) { // fill data + u16 *dram = Pico32xMem->dram[(Pico32x.vdp_regs[0x0a/2] & P32XV_FS) ^ 1]; + int len = Pico32x.vdp_regs[4 / 2] + 1; + int len1 = len; + a = Pico32x.vdp_regs[6 / 2]; + while (len1--) { + dram[a] = d; + a = (a & 0xff00) | ((a + 1) & 0xff); + } + Pico32x.vdp_regs[0x06 / 2] = a; + Pico32x.vdp_regs[0x08 / 2] = d; + if (sh2 != NULL && len > 4) { + Pico32x.vdp_regs[0x0a / 2] |= P32XV_nFEN; + // supposedly takes 3 bus/6 sh2 cycles? or 3 sh2 cycles? + p32x_event_schedule_sh2(sh2, P32X_EVENT_FILLEND, 3 + len); + } + return; + } + + p32x_vdp_write8(a | 1, d); +} + +// ------------------------------------------------------------------ +// SH2 regs + +static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2) +{ + u16 *r = Pico32x.regs; + a &= 0x3e; + + switch (a) { + case 0x00: // adapter/irq ctl + return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0] + | Pico32x.sh2irq_mask[sh2->is_slave]; + case 0x04: // H count (often as comm too) + sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); + sh2s_sync_on_read(sh2); + return Pico32x.sh2_regs[4 / 2]; + case 0x06: + return (r[a / 2] & ~P32XS_FULL) | 0x4000; + case 0x08: // DREQ src + case 0x0a: + case 0x0c: // DREQ dst + case 0x0e: + case 0x10: // DREQ len + return r[a / 2]; + case 0x12: // DREQ FIFO - does this work on hw? + if (Pico32x.dmac0_fifo_ptr > 0) { + Pico32x.dmac0_fifo_ptr--; + r[a / 2] = Pico32x.dmac_fifo[0]; + memmove(&Pico32x.dmac_fifo[0], &Pico32x.dmac_fifo[1], + Pico32x.dmac0_fifo_ptr * 2); + } + return r[a / 2]; + case 0x14: + case 0x16: + case 0x18: + case 0x1a: + case 0x1c: + return 0; // ? + } + + // comm port + if ((a & 0x30) == 0x20) { + int comreg = 1 << (a & 0x0f) / 2; + if (Pico32x.comm_dirty_68k & comreg) + Pico32x.comm_dirty_68k &= ~comreg; + else + sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3); + sh2s_sync_on_read(sh2); + return r[a / 2]; + } + if ((a & 0x30) == 0x30) + return p32x_pwm_read16(a, sh2, sh2_cycles_done_m68k(sh2)); + + elprintf_sh2(sh2, EL_32X|EL_ANOMALY, + "unhandled sysreg r16 [%02x] @%08x", a, sh2_pc(sh2)); + return 0; +} + +static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2) +{ + u16 *r = Pico32x.regs; + u32 old; + + a &= 0x3f; + sh2->poll_addr = 0; + + switch (a) { + case 0x00: // FM + r[0] &= ~P32XS_FM; + r[0] |= (d << 8) & P32XS_FM; + return; + case 0x01: // HEN/irq masks + old = Pico32x.sh2irq_mask[sh2->is_slave]; + if ((d ^ old) & 1) + p32x_pwm_sync_to_sh2(sh2); + + Pico32x.sh2irq_mask[sh2->is_slave] = d & 0x0f; + Pico32x.sh2_regs[0] &= ~0x80; + Pico32x.sh2_regs[0] |= d & 0x80; + + if ((d ^ old) & 1) + p32x_pwm_schedule_sh2(sh2); + if ((old ^ d) & 2) + p32x_update_cmd_irq(sh2, 0); + if ((old ^ d) & 4) + p32x_schedule_hint(sh2, 0); + return; + case 0x04: // ignored? + return; + case 0x05: // H count + d &= 0xff; + if (Pico32x.sh2_regs[4 / 2] != d) { + Pico32x.sh2_regs[4 / 2] = d; + p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, + sh2_cycles_done_m68k(sh2)); + sh2_end_run(sh2, 4); + } + return; + case 0x30: + REG8IN16(r, a) = d & 0x0f; + d = r[0x30 / 2]; + goto pwm_write; + case 0x31: // PWM control + REG8IN16(r, a) = d & 0x8f; + d = r[0x30 / 2]; + goto pwm_write; + case 0x32: // PWM cycle + REG8IN16(r, a) = d & 0x0f; + d = r[0x32 / 2]; + goto pwm_write; + case 0x33: + REG8IN16(r, a) = d; + d = r[0x32 / 2]; + goto pwm_write; + // PWM pulse regs.. Only writes to odd address send a value + // to FIFO; reads are 0 (except status bits) + case 0x34: + case 0x36: + case 0x38: + REG8IN16(r, a) = d; + return; + case 0x35: + case 0x37: + case 0x39: + d = (REG8IN16(r, a ^ 1) << 8) | (d & 0xff); + REG8IN16(r, a ^ 1) = 0; + goto pwm_write; + case 0x3a: // ignored, always 0? + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + case 0x3f: + return; + pwm_write: + p32x_pwm_write16(a & ~1, d, sh2, 0); + return; + } + + if ((a & 0x30) == 0x20) { + int comreg; + if (REG8IN16(r, a) == d) + return; + + REG8IN16(r, a) = d; + p32x_m68k_poll_event(P32XF_68KCPOLL); + p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, + sh2_cycles_done_m68k(sh2)); + comreg = 1 << (a & 0x0f) / 2; + Pico32x.comm_dirty_sh2 |= comreg; + return; + } + + elprintf(EL_32X|EL_ANOMALY, + "unhandled sysreg w8 [%02x] %02x @%08x", a, d, sh2_pc(sh2)); +} + +static void p32x_sh2reg_write16(u32 a, u32 d, SH2 *sh2) +{ + a &= 0x3e; + + sh2->poll_addr = 0; + + // comm + if ((a & 0x30) == 0x20) { + int comreg; + if (Pico32x.regs[a / 2] == d) + return; + + Pico32x.regs[a / 2] = d; + p32x_m68k_poll_event(P32XF_68KCPOLL); + p32x_sh2_poll_event(sh2->other_sh2, SH2_STATE_CPOLL, + sh2_cycles_done_m68k(sh2)); + comreg = 1 << (a & 0x0f) / 2; + Pico32x.comm_dirty_sh2 |= comreg; + return; + } + // PWM + else if ((a & 0x30) == 0x30) { + p32x_pwm_write16(a, d, sh2, sh2_cycles_done_m68k(sh2)); + return; + } + + switch (a) { + case 0: // FM + Pico32x.regs[0] &= ~P32XS_FM; + Pico32x.regs[0] |= d & P32XS_FM; + break; + case 0x14: + Pico32x.sh2irqs &= ~P32XI_VRES; + goto irls; + case 0x16: + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_VINT; + goto irls; + case 0x18: + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_HINT; + goto irls; + case 0x1a: + Pico32x.regs[2 / 2] &= ~(1 << sh2->is_slave); + p32x_update_cmd_irq(sh2, 0); + return; + case 0x1c: + p32x_pwm_sync_to_sh2(sh2); + Pico32x.sh2irqi[sh2->is_slave] &= ~P32XI_PWM; + p32x_pwm_schedule_sh2(sh2); + goto irls; + } + + p32x_sh2reg_write8(a | 1, d, sh2); + return; + +irls: + p32x_update_irls(sh2, 0); +} + +// ------------------------------------------------------------------ +// 32x 68k handlers + +// after ADEN +static u32 PicoRead8_32x_on(u32 a) +{ + u32 d = 0; + if ((a & 0xffc0) == 0x5100) { // a15100 + d = p32x_reg_read16(a); + goto out_16to8; + } + + if ((a & 0xfc00) != 0x5000) { + if (PicoAHW & PAHW_MCD) + return PicoRead8_mcd_io(a); + else + return PicoRead8_io(a); + } + + if ((a & 0xfff0) == 0x5180) { // a15180 + d = p32x_vdp_read16(a); + goto out_16to8; + } + + if ((a & 0xfe00) == 0x5200) { // a15200 + d = Pico32xMem->pal[(a & 0x1ff) / 2]; + goto out_16to8; + } + + if ((a & 0xfffc) == 0x30ec) { // a130ec + d = str_mars[a & 3]; + goto out; + } + + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return d; + +out_16to8: + if (a & 1) + d &= 0xff; + else + d >>= 8; + +out: + elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc); + return d; +} + +static u32 PicoRead16_32x_on(u32 a) +{ + u32 d = 0; + if ((a & 0xffc0) == 0x5100) { // a15100 + d = p32x_reg_read16(a); + goto out; + } + + if ((a & 0xfc00) != 0x5000) { + if (PicoAHW & PAHW_MCD) + return PicoRead16_mcd_io(a); + else + return PicoRead16_io(a); + } + + if ((a & 0xfff0) == 0x5180) { // a15180 + d = p32x_vdp_read16(a); + goto out; + } + + if ((a & 0xfe00) == 0x5200) { // a15200 + d = Pico32xMem->pal[(a & 0x1ff) / 2]; + goto out; + } + + if ((a & 0xfffc) == 0x30ec) { // a130ec + d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S'; + goto out; + } + + elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + return d; + +out: + elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc); + return d; +} + +static void PicoWrite8_32x_on(u32 a, u32 d) +{ + if ((a & 0xfc00) == 0x5000) + elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + + if ((a & 0xffc0) == 0x5100) { // a15100 + p32x_reg_write8(a, d); + return; + } + + if ((a & 0xfc00) != 0x5000) { + if (PicoAHW & PAHW_MCD) + PicoWrite8_mcd_io(a, d); + else + PicoWrite8_io(a, d); + if (a == 0xa130f1) + bank_switch(Pico32x.regs[4 / 2]); + return; + } + + if (!(Pico32x.regs[0] & P32XS_FM)) { + if ((a & 0xfff0) == 0x5180) { // a15180 + p32x_vdp_write8(a, d); + return; + } + + // TODO: verify + if ((a & 0xfe00) == 0x5200) { // a15200 + elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d; + Pico32x.dirty_pal = 1; + return; + } + } + + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); +} + +static void PicoWrite16_32x_on(u32 a, u32 d) +{ + if ((a & 0xfc00) == 0x5000) + elprintf(EL_32X, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + + if ((a & 0xffc0) == 0x5100) { // a15100 + p32x_reg_write16(a, d); + return; + } + + if ((a & 0xfc00) != 0x5000) { + if (PicoAHW & PAHW_MCD) + PicoWrite16_mcd_io(a, d); + else + PicoWrite16_io(a, d); + if (a == 0xa130f0) + bank_switch(Pico32x.regs[4 / 2]); + return; + } + + if (!(Pico32x.regs[0] & P32XS_FM)) { + if ((a & 0xfff0) == 0x5180) { // a15180 + p32x_vdp_write16(a, d, NULL); // FIXME? + return; + } + + if ((a & 0xfe00) == 0x5200) { // a15200 + Pico32xMem->pal[(a & 0x1ff) / 2] = d; + Pico32x.dirty_pal = 1; + return; + } + } + + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + +// before ADEN +u32 PicoRead8_32x(u32 a) +{ + u32 d = 0; + if ((a & 0xffc0) == 0x5100) { // a15100 + // regs are always readable + d = ((u8 *)Pico32x.regs)[(a & 0x3f) ^ 1]; + goto out; + } + + if ((a & 0xfffc) == 0x30ec) { // a130ec + d = str_mars[a & 3]; + goto out; + } + + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return d; + +out: + elprintf(EL_32X, "m68k 32x r8 [%06x] %02x @%06x", a, d, SekPc); + return d; +} + +u32 PicoRead16_32x(u32 a) +{ + u32 d = 0; + if ((a & 0xffc0) == 0x5100) { // a15100 + d = Pico32x.regs[(a & 0x3f) / 2]; + goto out; + } + + if ((a & 0xfffc) == 0x30ec) { // a130ec + d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S'; + goto out; + } + + elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + return d; + +out: + elprintf(EL_32X, "m68k 32x r16 [%06x] %04x @%06x", a, d, SekPc); + return d; +} + +void PicoWrite8_32x(u32 a, u32 d) +{ + if ((a & 0xffc0) == 0x5100) { // a15100 + u16 *r = Pico32x.regs; + + elprintf(EL_32X, "m68k 32x w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + a &= 0x3f; + if (a == 1) { + if ((d ^ r[0]) & d & P32XS_ADEN) { + Pico32xStartup(); + r[0] &= ~P32XS_nRES; // causes reset if specified by this write + r[0] |= P32XS_ADEN; + p32x_reg_write8(a, d); // forward for reset processing + } + return; + } + + // allow only COMM for now + if ((a & 0x30) == 0x20) { + u8 *r8 = (u8 *)r; + r8[a ^ 1] = d; + } + return; + } + + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); +} + +void PicoWrite16_32x(u32 a, u32 d) +{ + if ((a & 0xffc0) == 0x5100) { // a15100 + u16 *r = Pico32x.regs; + + elprintf(EL_UIO, "m68k 32x w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + a &= 0x3e; + if (a == 0) { + if ((d ^ r[0]) & d & P32XS_ADEN) { + Pico32xStartup(); + r[0] &= ~P32XS_nRES; // causes reset if specified by this write + r[0] |= P32XS_ADEN; + p32x_reg_write16(a, d); // forward for reset processing + } + return; + } + + // allow only COMM for now + if ((a & 0x30) == 0x20) + r[a / 2] = d; + return; + } + + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + +/* quirk: in both normal and overwrite areas only nonzero values go through */ +#define sh2_write8_dramN(n) \ + if ((d & 0xff) != 0) { \ + u8 *dram = (u8 *)Pico32xMem->dram[n]; \ + dram[(a & 0x1ffff) ^ 1] = d; \ + } + +static void m68k_write8_dram0_ow(u32 a, u32 d) +{ + sh2_write8_dramN(0); +} + +static void m68k_write8_dram1_ow(u32 a, u32 d) +{ + sh2_write8_dramN(1); +} + +#define sh2_write16_dramN(n) \ + u16 *pd = &Pico32xMem->dram[n][(a & 0x1ffff) / 2]; \ + if (!(a & 0x20000)) { \ + *pd = d; \ + return; \ + } \ + /* overwrite */ \ + if (!(d & 0xff00)) d |= *pd & 0xff00; \ + if (!(d & 0x00ff)) d |= *pd & 0x00ff; \ + *pd = d; + +static void m68k_write16_dram0_ow(u32 a, u32 d) +{ + sh2_write16_dramN(0); +} + +static void m68k_write16_dram1_ow(u32 a, u32 d) +{ + sh2_write16_dramN(1); +} + +// ----------------------------------------------------------------- + +// hint vector is writeable +static void PicoWrite8_hint(u32 a, u32 d) +{ + if ((a & 0xfffc) == 0x0070) { + Pico32xMem->m68k_rom[a ^ 1] = d; + return; + } + + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); +} + +static void PicoWrite16_hint(u32 a, u32 d) +{ + if ((a & 0xfffc) == 0x0070) { + ((u16 *)Pico32xMem->m68k_rom)[a/2] = d; + return; + } + + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", + a, d & 0xffff, SekPc); +} + +// normally not writable, but somebody could make a RAM cart +static void PicoWrite8_cart(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + + a &= 0xfffff; + m68k_write8(a, d); +} + +static void PicoWrite16_cart(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + + a &= 0xfffff; + m68k_write16(a, d); +} + +// same with bank, but save ram is sometimes here +static u32 PicoRead8_bank(u32 a) +{ + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + return m68k_read8(a); +} + +static u32 PicoRead16_bank(u32 a) +{ + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + return m68k_read16(a); +} + +static void PicoWrite8_bank(u32 a, u32 d) +{ + if (!(Pico.m.sram_reg & SRR_MAPPED)) + elprintf(EL_UIO, "m68k w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); + + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + m68k_write8(a, d); +} + +static void PicoWrite16_bank(u32 a, u32 d) +{ + if (!(Pico.m.sram_reg & SRR_MAPPED)) + elprintf(EL_UIO, "m68k w16 [%06x] %04x @%06x", + a, d & 0xffff, SekPc); + + a = (Pico32x.regs[4 / 2] << 20) | (a & 0xfffff); + m68k_write16(a, d); +} + +static void bank_map_handler(void) +{ + cpu68k_map_set(m68k_read8_map, 0x900000, 0x9fffff, PicoRead8_bank, 1); + cpu68k_map_set(m68k_read16_map, 0x900000, 0x9fffff, PicoRead16_bank, 1); +} + +static void bank_switch(int b) +{ + unsigned int rs, bank; + + if (Pico.m.ncart_in) + return; + + bank = b << 20; + if ((Pico.m.sram_reg & SRR_MAPPED) && bank == SRam.start) { + bank_map_handler(); + return; + } + + if (bank >= Pico.romsize) { + elprintf(EL_32X|EL_ANOMALY, "missing bank @ %06x", bank); + bank_map_handler(); + return; + } + + // 32X ROM (unbanked, XXX: consider mirroring?) + rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK; + rs -= bank; + if (rs > 0x100000) + rs = 0x100000; + cpu68k_map_set(m68k_read8_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0); + cpu68k_map_set(m68k_read16_map, 0x900000, 0x900000 + rs - 1, Pico.rom + bank, 0); + + elprintf(EL_32X, "bank %06x-%06x -> %06x", 0x900000, 0x900000 + rs - 1, bank); + +#ifdef EMU_F68K + // setup FAME fetchmap + for (rs = 0x90; rs < 0xa0; rs++) + PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom + bank - 0x900000; +#endif +} + +// ----------------------------------------------------------------- +// SH2 +// ----------------------------------------------------------------- + +// read8 +static u32 sh2_read8_unmapped(u32 a, SH2 *sh2) +{ + elprintf_sh2(sh2, EL_32X, "unmapped r8 [%08x] %02x @%06x", + a, 0, sh2_pc(sh2)); + return 0; +} + +static u32 sh2_read8_cs0(u32 a, SH2 *sh2) +{ + u32 d = 0; + + sh2_burn_cycles(sh2, 1*2); + + // 0x3ffc0 is veridied + if ((a & 0x3ffc0) == 0x4000) { + d = p32x_sh2reg_read16(a, sh2); + goto out_16to8; + } + + if ((a & 0x3fff0) == 0x4100) { + d = p32x_vdp_read16(a); + sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); + goto out_16to8; + } + + // TODO: mirroring? + if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m)) + return Pico32xMem->sh2_rom_m.b[a ^ 1]; + if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s)) + return Pico32xMem->sh2_rom_s.b[a ^ 1]; + + if ((a & 0x3fe00) == 0x4200) { + d = Pico32xMem->pal[(a & 0x1ff) / 2]; + goto out_16to8; + } + + return sh2_read8_unmapped(a, sh2); + +out_16to8: + if (a & 1) + d &= 0xff; + else + d >>= 8; + + elprintf_sh2(sh2, EL_32X, "r8 [%08x] %02x @%06x", + a, d, sh2_pc(sh2)); + return d; +} + +static u32 sh2_read8_da(u32 a, SH2 *sh2) +{ + return sh2->data_array[(a & 0xfff) ^ 1]; +} + +// read16 +static u32 sh2_read16_unmapped(u32 a, SH2 *sh2) +{ + elprintf_sh2(sh2, EL_32X, "unmapped r16 [%08x] %04x @%06x", + a, 0, sh2_pc(sh2)); + return 0; +} + +static u32 sh2_read16_cs0(u32 a, SH2 *sh2) +{ + u32 d = 0; + + sh2_burn_cycles(sh2, 1*2); + + if ((a & 0x3ffc0) == 0x4000) { + d = p32x_sh2reg_read16(a, sh2); + if (!(EL_LOGMASK & EL_PWM) && (a & 0x30) == 0x30) // hide PWM + return d; + goto out; + } + + if ((a & 0x3fff0) == 0x4100) { + d = p32x_vdp_read16(a); + sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7); + goto out; + } + + if (!sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_m)) + return Pico32xMem->sh2_rom_m.w[a / 2]; + if (sh2->is_slave && a < sizeof(Pico32xMem->sh2_rom_s)) + return Pico32xMem->sh2_rom_s.w[a / 2]; + + if ((a & 0x3fe00) == 0x4200) { + d = Pico32xMem->pal[(a & 0x1ff) / 2]; + goto out; + } + + return sh2_read16_unmapped(a, sh2); + +out: + elprintf_sh2(sh2, EL_32X, "r16 [%08x] %04x @%06x", + a, d, sh2_pc(sh2)); + return d; +} + +static u32 sh2_read16_da(u32 a, SH2 *sh2) +{ + return ((u16 *)sh2->data_array)[(a & 0xfff) / 2]; +} + +// writes +static void REGPARM(3) sh2_write_ignore(u32 a, u32 d, SH2 *sh2) +{ +} + +// write8 +static void REGPARM(3) sh2_write8_unmapped(u32 a, u32 d, SH2 *sh2) +{ + elprintf_sh2(sh2, EL_32X, "unmapped w8 [%08x] %02x @%06x", + a, d & 0xff, sh2_pc(sh2)); +} + +static void REGPARM(3) sh2_write8_cs0(u32 a, u32 d, SH2 *sh2) +{ + elprintf_sh2(sh2, EL_32X, "w8 [%08x] %02x @%06x", + a, d & 0xff, sh2_pc(sh2)); + + if (Pico32x.regs[0] & P32XS_FM) { + if ((a & 0x3fff0) == 0x4100) { + sh2->poll_addr = 0; + p32x_vdp_write8(a, d); + return; + } + } + + if ((a & 0x3ffc0) == 0x4000) { + p32x_sh2reg_write8(a, d, sh2); + return; + } + + sh2_write8_unmapped(a, d, sh2); +} + +static void REGPARM(3) sh2_write8_dram0(u32 a, u32 d, SH2 *sh2) +{ + sh2_write8_dramN(0); +} + +static void REGPARM(3) sh2_write8_dram1(u32 a, u32 d, SH2 *sh2) +{ + sh2_write8_dramN(1); +} + +static void REGPARM(3) sh2_write8_sdram(u32 a, u32 d, SH2 *sh2) +{ + u32 a1 = a & 0x3ffff; +#ifdef DRC_SH2 + int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT]; + if (t) + sh2_drc_wcheck_ram(a, t, sh2->is_slave); +#endif + Pico32xMem->sdram[a1 ^ 1] = d; +} + +static void REGPARM(3) sh2_write8_sdram_wt(u32 a, u32 d, SH2 *sh2) +{ + // xmen sync hack.. + if (a < 0x26000200) + sh2_end_run(sh2, 32); + + sh2_write8_sdram(a, d, sh2); +} + +static void REGPARM(3) sh2_write8_da(u32 a, u32 d, SH2 *sh2) +{ + u32 a1 = a & 0xfff; +#ifdef DRC_SH2 + int id = sh2->is_slave; + int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT]; + if (t) + sh2_drc_wcheck_da(a, t, id); +#endif + sh2->data_array[a1 ^ 1] = d; +} + +// write16 +static void REGPARM(3) sh2_write16_unmapped(u32 a, u32 d, SH2 *sh2) +{ + elprintf_sh2(sh2, EL_32X, "unmapped w16 [%08x] %04x @%06x", + a, d & 0xffff, sh2_pc(sh2)); +} + +static void REGPARM(3) sh2_write16_cs0(u32 a, u32 d, SH2 *sh2) +{ + if (((EL_LOGMASK & EL_PWM) || (a & 0x30) != 0x30)) // hide PWM + elprintf_sh2(sh2, EL_32X, "w16 [%08x] %04x @%06x", + a, d & 0xffff, sh2_pc(sh2)); + + if (Pico32x.regs[0] & P32XS_FM) { + if ((a & 0x3fff0) == 0x4100) { + sh2->poll_addr = 0; + p32x_vdp_write16(a, d, sh2); + return; + } + + if ((a & 0x3fe00) == 0x4200) { + Pico32xMem->pal[(a & 0x1ff) / 2] = d; + Pico32x.dirty_pal = 1; + return; + } + } + + if ((a & 0x3ffc0) == 0x4000) { + p32x_sh2reg_write16(a, d, sh2); + return; + } + + sh2_write16_unmapped(a, d, sh2); +} + +static void REGPARM(3) sh2_write16_dram0(u32 a, u32 d, SH2 *sh2) +{ + sh2_write16_dramN(0); +} + +static void REGPARM(3) sh2_write16_dram1(u32 a, u32 d, SH2 *sh2) +{ + sh2_write16_dramN(1); +} + +static void REGPARM(3) sh2_write16_sdram(u32 a, u32 d, SH2 *sh2) +{ + u32 a1 = a & 0x3ffff; +#ifdef DRC_SH2 + int t = Pico32xMem->drcblk_ram[a1 >> SH2_DRCBLK_RAM_SHIFT]; + if (t) + sh2_drc_wcheck_ram(a, t, sh2->is_slave); +#endif + ((u16 *)Pico32xMem->sdram)[a1 / 2] = d; +} + +static void REGPARM(3) sh2_write16_da(u32 a, u32 d, SH2 *sh2) +{ + u32 a1 = a & 0xfff; +#ifdef DRC_SH2 + int id = sh2->is_slave; + int t = Pico32xMem->drcblk_da[id][a1 >> SH2_DRCBLK_DA_SHIFT]; + if (t) + sh2_drc_wcheck_da(a, t, id); +#endif + ((u16 *)sh2->data_array)[a1 / 2] = d; +} + + +typedef u32 (sh2_read_handler)(u32 a, SH2 *sh2); +typedef void REGPARM(3) (sh2_write_handler)(u32 a, u32 d, SH2 *sh2); + +#define SH2MAP_ADDR2OFFS_R(a) \ + ((u32)(a) >> SH2_READ_SHIFT) + +#define SH2MAP_ADDR2OFFS_W(a) \ + ((u32)(a) >> SH2_WRITE_SHIFT) + +u32 REGPARM(2) p32x_sh2_read8(u32 a, SH2 *sh2) +{ + const sh2_memmap *sh2_map = sh2->read8_map; + uptr p; + + sh2_map += SH2MAP_ADDR2OFFS_R(a); + p = sh2_map->addr; + if (map_flag_set(p)) + return ((sh2_read_handler *)(p << 1))(a, sh2); + else + return *(u8 *)((p << 1) + ((a & sh2_map->mask) ^ 1)); +} + +u32 REGPARM(2) p32x_sh2_read16(u32 a, SH2 *sh2) +{ + const sh2_memmap *sh2_map = sh2->read16_map; + uptr p; + + sh2_map += SH2MAP_ADDR2OFFS_R(a); + p = sh2_map->addr; + if (map_flag_set(p)) + return ((sh2_read_handler *)(p << 1))(a, sh2); + else + return *(u16 *)((p << 1) + ((a & sh2_map->mask) & ~1)); +} + +u32 REGPARM(2) p32x_sh2_read32(u32 a, SH2 *sh2) +{ + const sh2_memmap *sh2_map = sh2->read16_map; + sh2_read_handler *handler; + u32 offs; + uptr p; + + offs = SH2MAP_ADDR2OFFS_R(a); + sh2_map += offs; + p = sh2_map->addr; + if (!map_flag_set(p)) { + // XXX: maybe 32bit access instead with ror? + u16 *pd = (u16 *)((p << 1) + ((a & sh2_map->mask) & ~1)); + return (pd[0] << 16) | pd[1]; + } + + if (offs == SH2MAP_ADDR2OFFS_R(0xffffc000)) + return sh2_peripheral_read32(a, sh2); + + handler = (sh2_read_handler *)(p << 1); + return (handler(a, sh2) << 16) | handler(a + 2, sh2); +} + +void REGPARM(3) p32x_sh2_write8(u32 a, u32 d, SH2 *sh2) +{ + const void **sh2_wmap = sh2->write8_tab; + sh2_write_handler *wh; + + wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)]; + wh(a, d, sh2); +} + +void REGPARM(3) p32x_sh2_write16(u32 a, u32 d, SH2 *sh2) +{ + const void **sh2_wmap = sh2->write16_tab; + sh2_write_handler *wh; + + wh = sh2_wmap[SH2MAP_ADDR2OFFS_W(a)]; + wh(a, d, sh2); +} + +void REGPARM(3) p32x_sh2_write32(u32 a, u32 d, SH2 *sh2) +{ + const void **sh2_wmap = sh2->write16_tab; + sh2_write_handler *wh; + u32 offs; + + offs = SH2MAP_ADDR2OFFS_W(a); + + if (offs == SH2MAP_ADDR2OFFS_W(0xffffc000)) { + sh2_peripheral_write32(a, d, sh2); + return; + } + + wh = sh2_wmap[offs]; + wh(a, d >> 16, sh2); + wh(a + 2, d, sh2); +} + +// ----------------------------------------------------------------- + +static void z80_md_bank_write_32x(unsigned int a, unsigned char d) +{ + unsigned int addr68k; + + addr68k = Pico.m.z80_bank68k << 15; + addr68k += a & 0x7fff; + if ((addr68k & 0xfff000) == 0xa15000) + Pico32x.emu_flags |= P32XF_Z80_32X_IO; + + elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, d); + m68k_write8(addr68k, d); +} + +// ----------------------------------------------------------------- + +static const u16 msh2_code[] = { + // trap instructions + 0xaffe, // 200 bra + 0x0009, // 202 nop + // have to wait a bit until m68k initial program finishes clearing stuff + // to avoid races with game SH2 code, like in Tempo + 0xd406, // 204 mov.l @(_m_ok,pc), r4 + 0xc400, // 206 mov.b @(h'0,gbr),r0 + 0xc801, // 208 tst #1, r0 + 0x8b0f, // 20a bf cd_start + 0xd105, // 20c mov.l @(_cnt,pc), r1 + 0xd206, // 20e mov.l @(_start,pc), r2 + 0x71ff, // 210 add #-1, r1 + 0x4115, // 212 cmp/pl r1 + 0x89fc, // 214 bt -2 + 0x6043, // 216 mov r4, r0 + 0xc208, // 218 mov.l r0, @(h'20,gbr) + 0x6822, // 21a mov.l @r2, r8 + 0x482b, // 21c jmp @r8 + 0x0009, // 21e nop + ('M'<<8)|'_', ('O'<<8)|'K', // 220 _m_ok + 0x0001, 0x0000, // 224 _cnt + 0x2200, 0x03e0, // master start pointer in ROM + // cd_start: + 0xd20d, // 22c mov.l @(__cd_,pc), r2 + 0xc608, // 22e mov.l @(h'20,gbr), r0 + 0x3200, // 230 cmp/eq r0, r2 + 0x8bfc, // 232 bf #-2 + 0xe000, // 234 mov #0, r0 + 0xcf80, // 236 or.b #0x80,@(r0,gbr) + 0xd80b, // 238 mov.l @(_start_cd,pc), r8 // 24000018 + 0xd30c, // 23a mov.l @(_max_len,pc), r3 + 0x5b84, // 23c mov.l @(h'10,r8), r11 // master vbr + 0x5a82, // 23e mov.l @(8,r8), r10 // entry + 0x5081, // 240 mov.l @(4,r8), r0 // len + 0x5980, // 242 mov.l @(0,r8), r9 // dst + 0x3036, // 244 cmp/hi r3,r0 + 0x8b00, // 246 bf #1 + 0x6033, // 248 mov r3,r0 + 0x7820, // 24a add #0x20, r8 + // ipl_copy: + 0x6286, // 24c mov.l @r8+, r2 + 0x2922, // 24e mov.l r2, @r9 + 0x7904, // 250 add #4, r9 + 0x70fc, // 252 add #-4, r0 + 0x8800, // 254 cmp/eq #0, r0 + 0x8bf9, // 256 bf #-5 + // + 0x4b2e, // 258 ldc r11, vbr + 0x6043, // 25a mov r4, r0 // M_OK + 0xc208, // 25c mov.l r0, @(h'20,gbr) + 0x4a2b, // 25e jmp @r10 + 0x0009, // 260 nop + 0x0009, // 262 nop // pad + ('_'<<8)|'C', ('D'<<8)|'_', // 264 __cd_ + 0x2400, 0x0018, // 268 _start_cd + 0x0001, 0xffe0, // 26c _max_len +}; + +static const u16 ssh2_code[] = { + 0xaffe, // 200 bra + 0x0009, // 202 nop + // code to wait for master, in case authentic master BIOS is used + 0xd106, // 204 mov.l @(_m_ok,pc), r1 + 0xd208, // 206 mov.l @(_start,pc), r2 + 0xc608, // 208 mov.l @(h'20,gbr), r0 + 0x3100, // 20a cmp/eq r0, r1 + 0x8bfc, // 20c bf #-2 + 0xc400, // 20e mov.b @(h'0,gbr),r0 + 0xc801, // 210 tst #1, r0 + 0xd004, // 212 mov.l @(_s_ok,pc), r0 + 0x8b0a, // 214 bf cd_start + 0xc209, // 216 mov.l r0, @(h'24,gbr) + 0x6822, // 218 mov.l @r2, r8 + 0x482b, // 21a jmp @r8 + 0x0009, // 21c nop + 0x0009, // 21e nop + ('M'<<8)|'_', ('O'<<8)|'K', // 220 + ('S'<<8)|'_', ('O'<<8)|'K', // 224 + 0x2200, 0x03e4, // slave start pointer in ROM + // cd_start: + 0xd803, // 22c mov.l @(_start_cd,pc), r8 // 24000018 + 0x5b85, // 22e mov.l @(h'14,r8), r11 // slave vbr + 0x5a83, // 230 mov.l @(h'0c,r8), r10 // entry + 0x4b2e, // 232 ldc r11, vbr + 0xc209, // 234 mov.l r0, @(h'24,gbr) // write S_OK + 0x4a2b, // 236 jmp @r10 + 0x0009, // 238 nop + 0x0009, // 23a nop + 0x2400, 0x0018, // 23c _start_cd +}; + +#define HWSWAP(x) (((u16)(x) << 16) | ((x) >> 16)) +static void get_bios(void) +{ + u16 *ps; + u32 *pl; + int i; + + // M68K ROM + if (p32x_bios_g != NULL) { + elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS"); + Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom)); + } + else { + // generate 68k ROM + ps = (u16 *)Pico32xMem->m68k_rom; + pl = (u32 *)ps; + for (i = 1; i < 0xc0/4; i++) + pl[i] = HWSWAP(0x880200 + (i - 1) * 6); + + // fill with nops + for (i = 0xc0/2; i < 0x100/2; i++) + ps[i] = 0x4e71; + +#if 0 + ps[0xc0/2] = 0x46fc; + ps[0xc2/2] = 0x2700; // move #0x2700,sr + ps[0xfe/2] = 0x60fe; // jump to self +#else + ps[0xfe/2] = 0x4e75; // rts +#endif + } + // fill remaining m68k_rom page with game ROM + memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom), + Pico.rom + sizeof(Pico32xMem->m68k_rom), + sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom)); + + // MSH2 + if (p32x_bios_m != NULL) { + elprintf(EL_STATUS|EL_32X, "32x: using supplied master SH2 BIOS"); + Byteswap(&Pico32xMem->sh2_rom_m, p32x_bios_m, sizeof(Pico32xMem->sh2_rom_m)); + } + else { + pl = (u32 *)&Pico32xMem->sh2_rom_m; + + // fill exception vector table to our trap address + for (i = 0; i < 128; i++) + pl[i] = HWSWAP(0x200); + + // start + pl[0] = pl[2] = HWSWAP(0x204); + // reset SP + pl[1] = pl[3] = HWSWAP(0x6040000); + + // startup code + memcpy(&Pico32xMem->sh2_rom_m.b[0x200], msh2_code, sizeof(msh2_code)); + } + + // SSH2 + if (p32x_bios_s != NULL) { + elprintf(EL_STATUS|EL_32X, "32x: using supplied slave SH2 BIOS"); + Byteswap(&Pico32xMem->sh2_rom_s, p32x_bios_s, sizeof(Pico32xMem->sh2_rom_s)); + } + else { + pl = (u32 *)&Pico32xMem->sh2_rom_s; + + // fill exception vector table to our trap address + for (i = 0; i < 128; i++) + pl[i] = HWSWAP(0x200); + + // start + pl[0] = pl[2] = HWSWAP(0x204); + // reset SP + pl[1] = pl[3] = HWSWAP(0x603f800); + + // startup code + memcpy(&Pico32xMem->sh2_rom_s.b[0x200], ssh2_code, sizeof(ssh2_code)); + } +} + +#define MAP_MEMORY(m) ((uptr)(m) >> 1) +#define MAP_HANDLER(h) ( ((uptr)(h) >> 1) | ((uptr)1 << (sizeof(uptr) * 8 - 1)) ) + +static sh2_memmap sh2_read8_map[0x80], sh2_read16_map[0x80]; +// for writes we are using handlers only +static sh2_write_handler *sh2_write8_map[0x80], *sh2_write16_map[0x80]; + +void Pico32xSwapDRAM(int b) +{ + cpu68k_map_set(m68k_read8_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0); + cpu68k_map_set(m68k_read16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0); + cpu68k_map_set(m68k_read8_map, 0x860000, 0x87ffff, Pico32xMem->dram[b], 0); + cpu68k_map_set(m68k_read16_map, 0x860000, 0x87ffff, Pico32xMem->dram[b], 0); + cpu68k_map_set(m68k_write8_map, 0x840000, 0x87ffff, + b ? m68k_write8_dram1_ow : m68k_write8_dram0_ow, 1); + cpu68k_map_set(m68k_write16_map, 0x840000, 0x87ffff, + b ? m68k_write16_dram1_ow : m68k_write16_dram0_ow, 1); + + // SH2 + sh2_read8_map[0x04/2].addr = sh2_read8_map[0x24/2].addr = + sh2_read16_map[0x04/2].addr = sh2_read16_map[0x24/2].addr = MAP_MEMORY(Pico32xMem->dram[b]); + + sh2_write8_map[0x04/2] = sh2_write8_map[0x24/2] = b ? sh2_write8_dram1 : sh2_write8_dram0; + sh2_write16_map[0x04/2] = sh2_write16_map[0x24/2] = b ? sh2_write16_dram1 : sh2_write16_dram0; +} + +void PicoMemSetup32x(void) +{ + unsigned int rs; + int i; + + Pico32xMem = malloc(sizeof(*Pico32xMem)); + if (Pico32xMem == NULL) { + elprintf(EL_STATUS, "OOM"); + return; + } + + get_bios(); + + // cartridge area becomes unmapped + // XXX: we take the easy way and don't unmap ROM, + // so that we can avoid handling the RV bit. + // m68k_map_unmap(0x000000, 0x3fffff); + + if (!Pico.m.ncart_in) { + // MD ROM area + rs = sizeof(Pico32xMem->m68k_rom_bank); + cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0); + cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0); + cpu68k_map_set(m68k_write8_map, 0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify + cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1); + + // 32X ROM (unbanked, XXX: consider mirroring?) + rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK; + if (rs > 0x80000) + rs = 0x80000; + cpu68k_map_set(m68k_read8_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_read16_map, 0x880000, 0x880000 + rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_write8_map, 0x880000, 0x880000 + rs - 1, PicoWrite8_cart, 1); + cpu68k_map_set(m68k_write16_map, 0x880000, 0x880000 + rs - 1, PicoWrite16_cart, 1); +#ifdef EMU_F68K + // setup FAME fetchmap + PicoCpuFM68k.Fetch[0] = (unsigned long)Pico32xMem->m68k_rom; + for (rs = 0x88; rs < 0x90; rs++) + PicoCpuFM68k.Fetch[rs] = (unsigned long)Pico.rom - 0x880000; +#endif + + // 32X ROM (banked) + bank_switch(0); + cpu68k_map_set(m68k_write8_map, 0x900000, 0x9fffff, PicoWrite8_bank, 1); + cpu68k_map_set(m68k_write16_map, 0x900000, 0x9fffff, PicoWrite16_bank, 1); + } + + // SYS regs + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_32x_on, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_32x_on, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_32x_on, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_32x_on, 1); + + // SH2 maps: A31,A30,A29,CS1,CS0 + // all unmapped by default + for (i = 0; i < ARRAY_SIZE(sh2_read8_map); i++) { + sh2_read8_map[i].addr = MAP_HANDLER(sh2_read8_unmapped); + sh2_read16_map[i].addr = MAP_HANDLER(sh2_read16_unmapped); + } + + for (i = 0; i < ARRAY_SIZE(sh2_write8_map); i++) { + sh2_write8_map[i] = sh2_write8_unmapped; + sh2_write16_map[i] = sh2_write16_unmapped; + } + + // "purge area" + for (i = 0x40; i <= 0x5f; i++) { + sh2_write8_map[i >> 1] = + sh2_write16_map[i >> 1] = sh2_write_ignore; + } + + // CS0 + sh2_read8_map[0x00/2].addr = sh2_read8_map[0x20/2].addr = MAP_HANDLER(sh2_read8_cs0); + sh2_read16_map[0x00/2].addr = sh2_read16_map[0x20/2].addr = MAP_HANDLER(sh2_read16_cs0); + sh2_write8_map[0x00/2] = sh2_write8_map[0x20/2] = sh2_write8_cs0; + sh2_write16_map[0x00/2] = sh2_write16_map[0x20/2] = sh2_write16_cs0; + // CS1 - ROM + sh2_read8_map[0x02/2].addr = sh2_read8_map[0x22/2].addr = + sh2_read16_map[0x02/2].addr = sh2_read16_map[0x22/2].addr = MAP_MEMORY(Pico.rom); + sh2_read8_map[0x02/2].mask = sh2_read8_map[0x22/2].mask = + sh2_read16_map[0x02/2].mask = sh2_read16_map[0x22/2].mask = 0x3fffff; // FIXME + // CS2 - DRAM - done by Pico32xSwapDRAM() + sh2_read8_map[0x04/2].mask = sh2_read8_map[0x24/2].mask = + sh2_read16_map[0x04/2].mask = sh2_read16_map[0x24/2].mask = 0x01ffff; + // CS3 - SDRAM + sh2_read8_map[0x06/2].addr = sh2_read8_map[0x26/2].addr = + sh2_read16_map[0x06/2].addr = sh2_read16_map[0x26/2].addr = MAP_MEMORY(Pico32xMem->sdram); + sh2_write8_map[0x06/2] = sh2_write8_sdram; + sh2_write8_map[0x26/2] = sh2_write8_sdram_wt; + sh2_write16_map[0x06/2] = sh2_write16_map[0x26/2] = sh2_write16_sdram; + sh2_read8_map[0x06/2].mask = sh2_read8_map[0x26/2].mask = + sh2_read16_map[0x06/2].mask = sh2_read16_map[0x26/2].mask = 0x03ffff; + // SH2 data array + sh2_read8_map[0xc0/2].addr = MAP_HANDLER(sh2_read8_da); + sh2_read16_map[0xc0/2].addr = MAP_HANDLER(sh2_read16_da); + sh2_write8_map[0xc0/2] = sh2_write8_da; + sh2_write16_map[0xc0/2] = sh2_write16_da; + // SH2 IO + sh2_read8_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read8); + sh2_read16_map[0xff/2].addr = MAP_HANDLER(sh2_peripheral_read16); + sh2_write8_map[0xff/2] = sh2_peripheral_write8; + sh2_write16_map[0xff/2] = sh2_peripheral_write16; + + // map DRAM area, both 68k and SH2 + Pico32xSwapDRAM(1); + + msh2.read8_map = ssh2.read8_map = sh2_read8_map; + msh2.read16_map = ssh2.read16_map = sh2_read16_map; + msh2.write8_tab = ssh2.write8_tab = (const void **)(void *)sh2_write8_map; + msh2.write16_tab = ssh2.write16_tab = (const void **)(void *)sh2_write16_map; + + // z80 hack + z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write_32x, 1); +} diff --git a/waterbox/picodrive/pico/32x/pwm.c b/waterbox/picodrive/pico/32x/pwm.c new file mode 100644 index 0000000000..1aba914f4f --- /dev/null +++ b/waterbox/picodrive/pico/32x/pwm.c @@ -0,0 +1,337 @@ +/* + * PicoDrive + * (C) notaz, 2009,2010,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include "../pico_int.h" + +static int pwm_cycles; +static int pwm_mult; +static int pwm_ptr; +static int pwm_irq_reload; +static int pwm_doing_fifo; +static int pwm_silent; + +void p32x_pwm_ctl_changed(void) +{ + int control = Pico32x.regs[0x30 / 2]; + int cycles = Pico32x.regs[0x32 / 2]; + + cycles = (cycles - 1) & 0x0fff; + pwm_cycles = cycles; + + // supposedly we should stop FIFO when xMd is 0, + // but mars test disagrees + pwm_mult = 0; + if ((control & 0x0f) != 0) + pwm_mult = 0x10000 / cycles; + + pwm_irq_reload = (control & 0x0f00) >> 8; + pwm_irq_reload = ((pwm_irq_reload - 1) & 0x0f) + 1; + + if (Pico32x.pwm_irq_cnt == 0) + Pico32x.pwm_irq_cnt = pwm_irq_reload; +} + +static void do_pwm_irq(SH2 *sh2, unsigned int m68k_cycles) +{ + p32x_trigger_irq(sh2, m68k_cycles, P32XI_PWM); + + if (Pico32x.regs[0x30 / 2] & P32XP_RTP) { + p32x_event_schedule(m68k_cycles, P32X_EVENT_PWM, pwm_cycles / 3 + 1); + // note: might recurse + p32x_dreq1_trigger(); + } +} + +static int convert_sample(unsigned int v) +{ + if (v == 0) + return 0; + if (v > pwm_cycles) + v = pwm_cycles; + return ((int)v - pwm_cycles / 2) * pwm_mult; +} + +#define consume_fifo(sh2, m68k_cycles) { \ + int cycles_diff = ((m68k_cycles) * 3) - Pico32x.pwm_cycle_p; \ + if (cycles_diff >= pwm_cycles) \ + consume_fifo_do(sh2, m68k_cycles, cycles_diff); \ +} + +static void consume_fifo_do(SH2 *sh2, unsigned int m68k_cycles, + int sh2_cycles_diff) +{ + struct Pico32xMem *mem = Pico32xMem; + unsigned short *fifo_l = mem->pwm_fifo[0]; + unsigned short *fifo_r = mem->pwm_fifo[1]; + int sum = 0; + + if (pwm_cycles == 0 || pwm_doing_fifo) + return; + + elprintf(EL_PWM, "pwm: %u: consume %d/%d, %d,%d ptr %d", + m68k_cycles, sh2_cycles_diff, sh2_cycles_diff / pwm_cycles, + Pico32x.pwm_p[0], Pico32x.pwm_p[1], pwm_ptr); + + // this is for recursion from dreq1 writes + pwm_doing_fifo = 1; + + for (; sh2_cycles_diff >= pwm_cycles; sh2_cycles_diff -= pwm_cycles) + { + if (Pico32x.pwm_p[0] > 0) { + fifo_l[0] = fifo_l[1]; + fifo_l[1] = fifo_l[2]; + fifo_l[2] = fifo_l[3]; + Pico32x.pwm_p[0]--; + mem->pwm_current[0] = convert_sample(fifo_l[0]); + sum += mem->pwm_current[0]; + } + if (Pico32x.pwm_p[1] > 0) { + fifo_r[0] = fifo_r[1]; + fifo_r[1] = fifo_r[2]; + fifo_r[2] = fifo_r[3]; + Pico32x.pwm_p[1]--; + mem->pwm_current[1] = convert_sample(fifo_r[0]); + sum += mem->pwm_current[1]; + } + + mem->pwm[pwm_ptr * 2 ] = mem->pwm_current[0]; + mem->pwm[pwm_ptr * 2 + 1] = mem->pwm_current[1]; + pwm_ptr = (pwm_ptr + 1) & (PWM_BUFF_LEN - 1); + + if (--Pico32x.pwm_irq_cnt == 0) { + Pico32x.pwm_irq_cnt = pwm_irq_reload; + do_pwm_irq(sh2, m68k_cycles); + } + } + Pico32x.pwm_cycle_p = m68k_cycles * 3 - sh2_cycles_diff; + pwm_doing_fifo = 0; + if (sum != 0) + pwm_silent = 0; +} + +static int p32x_pwm_schedule_(SH2 *sh2, unsigned int m68k_now) +{ + unsigned int sh2_now = m68k_now * 3; + int cycles_diff_sh2; + + if (pwm_cycles == 0) + return 0; + + cycles_diff_sh2 = sh2_now - Pico32x.pwm_cycle_p; + if (cycles_diff_sh2 >= pwm_cycles) + consume_fifo_do(sh2, m68k_now, cycles_diff_sh2); + + if (!((Pico32x.sh2irq_mask[0] | Pico32x.sh2irq_mask[1]) & 1)) + return 0; // masked by everyone + + cycles_diff_sh2 = sh2_now - Pico32x.pwm_cycle_p; + return (Pico32x.pwm_irq_cnt * pwm_cycles + - cycles_diff_sh2) / 3 + 1; +} + +void p32x_pwm_schedule(unsigned int m68k_now) +{ + int after = p32x_pwm_schedule_(NULL, m68k_now); + if (after != 0) + p32x_event_schedule(m68k_now, P32X_EVENT_PWM, after); +} + +void p32x_pwm_schedule_sh2(SH2 *sh2) +{ + int after = p32x_pwm_schedule_(sh2, sh2_cycles_done_m68k(sh2)); + if (after != 0) + p32x_event_schedule_sh2(sh2, P32X_EVENT_PWM, after); +} + +void p32x_pwm_sync_to_sh2(SH2 *sh2) +{ + int m68k_cycles = sh2_cycles_done_m68k(sh2); + consume_fifo(sh2, m68k_cycles); +} + +void p32x_pwm_irq_event(unsigned int m68k_now) +{ + p32x_pwm_schedule(m68k_now); +} + +unsigned int p32x_pwm_read16(unsigned int a, SH2 *sh2, + unsigned int m68k_cycles) +{ + unsigned int d = 0; + + consume_fifo(sh2, m68k_cycles); + + a &= 0x0e; + switch (a) { + case 0: // control + case 2: // cycle + d = Pico32x.regs[(0x30 + a) / 2]; + break; + + case 4: // L ch + if (Pico32x.pwm_p[0] == 3) + d |= P32XP_FULL; + else if (Pico32x.pwm_p[0] == 0) + d |= P32XP_EMPTY; + break; + + case 6: // R ch + case 8: // MONO + if (Pico32x.pwm_p[1] == 3) + d |= P32XP_FULL; + else if (Pico32x.pwm_p[1] == 0) + d |= P32XP_EMPTY; + break; + } + + elprintf(EL_PWM, "pwm: %u: r16 %02x %04x (p %d %d)", + m68k_cycles, a, d, Pico32x.pwm_p[0], Pico32x.pwm_p[1]); + return d; +} + +void p32x_pwm_write16(unsigned int a, unsigned int d, + SH2 *sh2, unsigned int m68k_cycles) +{ + elprintf(EL_PWM, "pwm: %u: w16 %02x %04x (p %d %d)", + m68k_cycles, a & 0x0e, d, Pico32x.pwm_p[0], Pico32x.pwm_p[1]); + + consume_fifo(sh2, m68k_cycles); + + a &= 0x0e; + if (a == 0) { // control + // avoiding pops.. + if ((Pico32x.regs[0x30 / 2] & 0x0f) == 0) + Pico32xMem->pwm_fifo[0][0] = Pico32xMem->pwm_fifo[1][0] = 0; + Pico32x.regs[0x30 / 2] = d; + p32x_pwm_ctl_changed(); + Pico32x.pwm_irq_cnt = pwm_irq_reload; // ? + } + else if (a == 2) { // cycle + Pico32x.regs[0x32 / 2] = d & 0x0fff; + p32x_pwm_ctl_changed(); + } + else if (a <= 8) { + d = (d - 1) & 0x0fff; + + if (a == 4 || a == 8) { // L ch or MONO + unsigned short *fifo = Pico32xMem->pwm_fifo[0]; + if (Pico32x.pwm_p[0] < 3) + Pico32x.pwm_p[0]++; + else { + fifo[1] = fifo[2]; + fifo[2] = fifo[3]; + } + fifo[Pico32x.pwm_p[0]] = d; + } + if (a == 6 || a == 8) { // R ch or MONO + unsigned short *fifo = Pico32xMem->pwm_fifo[1]; + if (Pico32x.pwm_p[1] < 3) + Pico32x.pwm_p[1]++; + else { + fifo[1] = fifo[2]; + fifo[2] = fifo[3]; + } + fifo[Pico32x.pwm_p[1]] = d; + } + } +} + +void p32x_pwm_update(int *buf32, int length, int stereo) +{ + short *pwmb; + int step; + int p = 0; + int xmd; + + consume_fifo(NULL, SekCyclesDone()); + + xmd = Pico32x.regs[0x30 / 2] & 0x0f; + if (xmd == 0 || xmd == 0x06 || xmd == 0x09 || xmd == 0x0f) + goto out; // invalid? + if (pwm_silent) + return; + + step = (pwm_ptr << 16) / length; + pwmb = Pico32xMem->pwm; + + if (stereo) + { + if (xmd == 0x05) { + // normal + while (length-- > 0) { + *buf32++ += pwmb[0]; + *buf32++ += pwmb[1]; + + p += step; + pwmb += (p >> 16) * 2; + p &= 0xffff; + } + } + else if (xmd == 0x0a) { + // channel swap + while (length-- > 0) { + *buf32++ += pwmb[1]; + *buf32++ += pwmb[0]; + + p += step; + pwmb += (p >> 16) * 2; + p &= 0xffff; + } + } + else { + // mono - LMD, RMD specify dst + if (xmd & 0x06) // src is R + pwmb++; + if (xmd & 0x0c) // dst is R + buf32++; + while (length-- > 0) { + *buf32 += *pwmb; + + p += step; + pwmb += (p >> 16) * 2; + p &= 0xffff; + buf32 += 2; + } + } + } + else + { + // mostly unused + while (length-- > 0) { + *buf32++ += pwmb[0]; + + p += step; + pwmb += (p >> 16) * 2; + p &= 0xffff; + } + } + + elprintf(EL_PWM, "pwm_update: pwm_ptr %d, len %d, step %04x, done %d", + pwm_ptr, length, step, (pwmb - Pico32xMem->pwm) / 2); + +out: + pwm_ptr = 0; + pwm_silent = Pico32xMem->pwm_current[0] == 0 + && Pico32xMem->pwm_current[1] == 0; +} + +void p32x_pwm_state_loaded(void) +{ + int cycles_diff_sh2; + + p32x_pwm_ctl_changed(); + + // for old savestates + cycles_diff_sh2 = SekCycleCnt * 3 - Pico32x.pwm_cycle_p; + if (cycles_diff_sh2 >= pwm_cycles || cycles_diff_sh2 < 0) { + Pico32x.pwm_irq_cnt = pwm_irq_reload; + Pico32x.pwm_cycle_p = SekCycleCnt * 3; + p32x_pwm_schedule(SekCycleCnt); + } +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/32x/sh2soc.c b/waterbox/picodrive/pico/32x/sh2soc.c new file mode 100644 index 0000000000..62423d1361 --- /dev/null +++ b/waterbox/picodrive/pico/32x/sh2soc.c @@ -0,0 +1,519 @@ +/* + * SH2 peripherals/"system on chip" + * (C) notaz, 2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + * + * rough fffffe00-ffffffff map: + * e00-e05 SCI serial communication interface + * e10-e1a FRT free-running timer + * e60-e68 VCRx irq vectors + * e71-e72 DRCR dma selection + * e80-e83 WDT watchdog timer + * e91 SBYCR standby control + * e92 CCR cache control + * ee0 ICR irq control + * ee2 IPRA irq priorities + * ee4 VCRWDT WDT irq vectors + * f00-f17 DIVU + * f40-f7b UBC user break controller + * f80-fb3 DMAC + * fe0-ffb BSC bus state controller + */ + +#include "../pico_int.h" +#include "../memory.h" + +// DMAC handling +struct dma_chan { + unsigned int sar, dar; // src, dst addr + unsigned int tcr; // transfer count + unsigned int chcr; // chan ctl + // -- dm dm sm sm ts ts ar am al ds dl tb ta ie te de + // ts - transfer size: 1, 2, 4, 16 bytes + // ar - auto request if 1, else dreq signal + // ie - irq enable + // te - transfer end + // de - dma enable + #define DMA_AR (1 << 9) + #define DMA_IE (1 << 2) + #define DMA_TE (1 << 1) + #define DMA_DE (1 << 0) +}; + +struct dmac { + struct dma_chan chan[2]; + unsigned int vcrdma0; + unsigned int unknown0; + unsigned int vcrdma1; + unsigned int unknown1; + unsigned int dmaor; + // -- pr ae nmif dme + // pr - priority: chan0 > chan1 or round-robin + // ae - address error + // nmif - nmi occurred + // dme - DMA master enable + #define DMA_DME (1 << 0) +}; + +static void dmac_te_irq(SH2 *sh2, struct dma_chan *chan) +{ + char *regs = (void *)sh2->peri_regs; + struct dmac *dmac = (void *)(regs + 0x180); + int level = PREG8(regs, 0xe2) & 0x0f; // IPRA + int vector = (chan == &dmac->chan[0]) ? + dmac->vcrdma0 : dmac->vcrdma1; + + elprintf(EL_32XP, "dmac irq %d %d", level, vector); + sh2_internal_irq(sh2, level, vector & 0x7f); +} + +static void dmac_transfer_complete(SH2 *sh2, struct dma_chan *chan) +{ + chan->chcr |= DMA_TE; // DMA has ended normally + + p32x_sh2_poll_event(sh2, SH2_STATE_SLEEP, SekCyclesDone()); + if (chan->chcr & DMA_IE) + dmac_te_irq(sh2, chan); +} + +static void dmac_transfer_one(SH2 *sh2, struct dma_chan *chan) +{ + u32 size, d; + + size = (chan->chcr >> 10) & 3; + switch (size) { + case 0: + d = p32x_sh2_read8(chan->sar, sh2); + p32x_sh2_write8(chan->dar, d, sh2); + case 1: + d = p32x_sh2_read16(chan->sar, sh2); + p32x_sh2_write16(chan->dar, d, sh2); + break; + case 2: + d = p32x_sh2_read32(chan->sar, sh2); + p32x_sh2_write32(chan->dar, d, sh2); + break; + case 3: + d = p32x_sh2_read32(chan->sar + 0x00, sh2); + p32x_sh2_write32(chan->dar + 0x00, d, sh2); + d = p32x_sh2_read32(chan->sar + 0x04, sh2); + p32x_sh2_write32(chan->dar + 0x04, d, sh2); + d = p32x_sh2_read32(chan->sar + 0x08, sh2); + p32x_sh2_write32(chan->dar + 0x08, d, sh2); + d = p32x_sh2_read32(chan->sar + 0x0c, sh2); + p32x_sh2_write32(chan->dar + 0x0c, d, sh2); + chan->sar += 16; // always? + if (chan->chcr & (1 << 15)) + chan->dar -= 16; + if (chan->chcr & (1 << 14)) + chan->dar += 16; + chan->tcr -= 4; + return; + } + chan->tcr--; + + size = 1 << size; + if (chan->chcr & (1 << 15)) + chan->dar -= size; + if (chan->chcr & (1 << 14)) + chan->dar += size; + if (chan->chcr & (1 << 13)) + chan->sar -= size; + if (chan->chcr & (1 << 12)) + chan->sar += size; +} + +// DMA trigger by SH2 register write +static void dmac_trigger(SH2 *sh2, struct dma_chan *chan) +{ + elprintf_sh2(sh2, EL_32XP, "DMA %08x->%08x, cnt %d, chcr %04x @%06x", + chan->sar, chan->dar, chan->tcr, chan->chcr, sh2->pc); + chan->tcr &= 0xffffff; + + if (chan->chcr & DMA_AR) { + // auto-request transfer + while ((int)chan->tcr > 0) + dmac_transfer_one(sh2, chan); + dmac_transfer_complete(sh2, chan); + return; + } + + // DREQ0 is only sent after first 4 words are written. + // we do multiple of 4 words to avoid messing up alignment + if ((chan->sar & ~0x20000000) == 0x00004012) { + if (Pico32x.dmac0_fifo_ptr && (Pico32x.dmac0_fifo_ptr & 3) == 0) { + elprintf(EL_32XP, "68k -> sh2 DMA"); + p32x_dreq0_trigger(); + } + return; + } + + // DREQ1 + if ((chan->dar & 0xc7fffff0) == 0x00004030) + return; + + elprintf(EL_32XP|EL_ANOMALY, "unhandled DMA: " + "%08x->%08x, cnt %d, chcr %04x @%06x", + chan->sar, chan->dar, chan->tcr, chan->chcr, sh2->pc); +} + +// timer state - FIXME +static int timer_cycles[2]; +static int timer_tick_cycles[2]; + +// timers +void p32x_timers_recalc(void) +{ + int cycles; + int tmp, i; + + // SH2 timer step + for (i = 0; i < 2; i++) { + tmp = PREG8(sh2s[i].peri_regs, 0x80) & 7; + // Sclk cycles per timer tick + if (tmp) + cycles = 0x20 << tmp; + else + cycles = 2; + timer_tick_cycles[i] = cycles; + timer_cycles[i] = 0; + elprintf(EL_32XP, "WDT cycles[%d] = %d", i, cycles); + } +} + +void p32x_timers_do(unsigned int m68k_slice) +{ + unsigned int cycles = m68k_slice * 3; + int cnt, i; + + // WDT timers + for (i = 0; i < 2; i++) { + void *pregs = sh2s[i].peri_regs; + if (PREG8(pregs, 0x80) & 0x20) { // TME + timer_cycles[i] += cycles; + cnt = PREG8(pregs, 0x81); + while (timer_cycles[i] >= timer_tick_cycles[i]) { + timer_cycles[i] -= timer_tick_cycles[i]; + cnt++; + } + if (cnt >= 0x100) { + int level = PREG8(pregs, 0xe3) >> 4; + int vector = PREG8(pregs, 0xe4) & 0x7f; + elprintf(EL_32XP, "%csh2 WDT irq (%d, %d)", + i ? 's' : 'm', level, vector); + sh2_internal_irq(&sh2s[i], level, vector); + cnt &= 0xff; + } + PREG8(pregs, 0x81) = cnt; + } + } +} + +void sh2_peripheral_reset(SH2 *sh2) +{ + memset(sh2->peri_regs, 0, sizeof(sh2->peri_regs)); // ? + PREG8(sh2->peri_regs, 0x001) = 0xff; // SCI BRR + PREG8(sh2->peri_regs, 0x003) = 0xff; // SCI TDR + PREG8(sh2->peri_regs, 0x004) = 0x84; // SCI SSR + PREG8(sh2->peri_regs, 0x011) = 0x01; // TIER + PREG8(sh2->peri_regs, 0x017) = 0xe0; // TOCR +} + +// ------------------------------------------------------------------ +// SH2 internal peripheral memhandlers +// we keep them in little endian format + +u32 sh2_peripheral_read8(u32 a, SH2 *sh2) +{ + u8 *r = (void *)sh2->peri_regs; + u32 d; + + a &= 0x1ff; + d = PREG8(r, a); + + elprintf_sh2(sh2, EL_32XP, "peri r8 [%08x] %02x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); + return d; +} + +u32 sh2_peripheral_read16(u32 a, SH2 *sh2) +{ + u16 *r = (void *)sh2->peri_regs; + u32 d; + + a &= 0x1ff; + d = r[(a / 2) ^ 1]; + + elprintf_sh2(sh2, EL_32XP, "peri r16 [%08x] %04x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); + return d; +} + +u32 sh2_peripheral_read32(u32 a, SH2 *sh2) +{ + u32 d; + a &= 0x1fc; + d = sh2->peri_regs[a / 4]; + + elprintf_sh2(sh2, EL_32XP, "peri r32 [%08x] %08x @%06x", + a | ~0x1ff, d, sh2_pc(sh2)); + return d; +} + +static void sci_trigger(SH2 *sh2, u8 *r) +{ + u8 *oregs; + + if (!(PREG8(r, 2) & 0x20)) + return; // transmitter not enabled + if ((PREG8(r, 4) & 0x80)) // TDRE - TransmitDataR Empty + return; + + oregs = (u8 *)sh2->other_sh2->peri_regs; + if (!(PREG8(oregs, 2) & 0x10)) + return; // receiver not enabled + + PREG8(oregs, 5) = PREG8(r, 3); // other.RDR = this.TDR + PREG8(r, 4) |= 0x80; // TDRE - TDR empty + PREG8(oregs, 4) |= 0x40; // RDRF - RDR Full + + // might need to delay these a bit.. + if (PREG8(r, 2) & 0x80) { // TIE - tx irq enabled + int level = PREG8(oregs, 0x60) >> 4; + int vector = PREG8(oregs, 0x64) & 0x7f; + elprintf_sh2(sh2, EL_32XP, "SCI tx irq (%d, %d)", + level, vector); + sh2_internal_irq(sh2, level, vector); + } + // TODO: TEIE + if (PREG8(oregs, 2) & 0x40) { // RIE - rx irq enabled + int level = PREG8(oregs, 0x60) >> 4; + int vector = PREG8(oregs, 0x63) & 0x7f; + elprintf_sh2(sh2->other_sh2, EL_32XP, "SCI rx irq (%d, %d)", + level, vector); + sh2_internal_irq(sh2->other_sh2, level, vector); + } +} + +void REGPARM(3) sh2_peripheral_write8(u32 a, u32 d, SH2 *sh2) +{ + u8 *r = (void *)sh2->peri_regs; + u8 old; + + elprintf_sh2(sh2, EL_32XP, "peri w8 [%08x] %02x @%06x", + a, d, sh2_pc(sh2)); + + a &= 0x1ff; + old = PREG8(r, a); + + switch (a) { + case 0x002: // SCR - serial control + if (!(PREG8(r, a) & 0x20) && (d & 0x20)) { // TE being set + PREG8(r, a) = d; + sci_trigger(sh2, r); + } + break; + case 0x003: // TDR - transmit data + break; + case 0x004: // SSR - serial status + d = (old & (d | 0x06)) | (d & 1); + PREG8(r, a) = d; + sci_trigger(sh2, r); + return; + case 0x005: // RDR - receive data + break; + case 0x010: // TIER + if (d & 0x8e) + elprintf(EL_32XP|EL_ANOMALY, "TIER: %02x", d); + d = (d & 0x8e) | 1; + break; + case 0x017: // TOCR + d |= 0xe0; + break; + } + PREG8(r, a) = d; +} + +void REGPARM(3) sh2_peripheral_write16(u32 a, u32 d, SH2 *sh2) +{ + u16 *r = (void *)sh2->peri_regs; + elprintf_sh2(sh2, EL_32XP, "peri w16 [%08x] %04x @%06x", + a, d, sh2_pc(sh2)); + + a &= 0x1ff; + + // evil WDT + if (a == 0x80) { + if ((d & 0xff00) == 0xa500) { // WTCSR + PREG8(r, 0x80) = d; + p32x_timers_recalc(); + } + if ((d & 0xff00) == 0x5a00) // WTCNT + PREG8(r, 0x81) = d; + return; + } + + r[(a / 2) ^ 1] = d; +} + +void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2) +{ + u32 *r = sh2->peri_regs; + u32 old; + + elprintf_sh2(sh2, EL_32XP, "peri w32 [%08x] %08x @%06x", + a, d, sh2_pc(sh2)); + + a &= 0x1fc; + old = r[a / 4]; + r[a / 4] = d; + + switch (a) { + // division unit (TODO: verify): + case 0x104: // DVDNT: divident L, starts divide + elprintf_sh2(sh2, EL_32XP, "divide %08x / %08x", + d, r[0x100 / 4]); + if (r[0x100 / 4]) { + signed int divisor = r[0x100 / 4]; + r[0x118 / 4] = r[0x110 / 4] = (signed int)d % divisor; + r[0x104 / 4] = r[0x11c / 4] = r[0x114 / 4] = (signed int)d / divisor; + } + else + r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ? + break; + case 0x114: + elprintf_sh2(sh2, EL_32XP, "divide %08x%08x / %08x @%08x", + r[0x110 / 4], d, r[0x100 / 4], sh2_pc(sh2)); + if (r[0x100 / 4]) { + signed long long divident = (signed long long)r[0x110 / 4] << 32 | d; + signed int divisor = r[0x100 / 4]; + // XXX: undocumented mirroring to 0x118,0x11c? + r[0x118 / 4] = r[0x110 / 4] = divident % divisor; + divident /= divisor; + r[0x11c / 4] = r[0x114 / 4] = divident; + divident >>= 31; + if ((unsigned long long)divident + 1 > 1) { + //elprintf_sh2(sh2, EL_32XP, "divide overflow! @%08x", sh2_pc(sh2)); + r[0x11c / 4] = r[0x114 / 4] = divident > 0 ? 0x7fffffff : 0x80000000; // overflow + } + } + else + r[0x110 / 4] = r[0x114 / 4] = r[0x118 / 4] = r[0x11c / 4] = 0; // ? + break; + } + + // perhaps starting a DMA? + if (a == 0x1b0 || a == 0x18c || a == 0x19c) { + struct dmac *dmac = (void *)&sh2->peri_regs[0x180 / 4]; + if (a == 0x1b0 && !((old ^ d) & d & DMA_DME)) + return; + if (!(dmac->dmaor & DMA_DME)) + return; + + if ((dmac->chan[0].chcr & (DMA_TE|DMA_DE)) == DMA_DE) + dmac_trigger(sh2, &dmac->chan[0]); + if ((dmac->chan[1].chcr & (DMA_TE|DMA_DE)) == DMA_DE) + dmac_trigger(sh2, &dmac->chan[1]); + } +} + +/* 32X specific */ +static void dreq0_do(SH2 *sh2, struct dma_chan *chan) +{ + unsigned short dreqlen = Pico32x.regs[0x10 / 2]; + int i; + + // debug/sanity checks + if (chan->tcr < dreqlen || chan->tcr > dreqlen + 4) + elprintf(EL_32XP|EL_ANOMALY, "dreq0: tcr0/len inconsistent: %d/%d", + chan->tcr, dreqlen); + // note: DACK is not connected, single addr mode should not be used + if ((chan->chcr & 0x3f08) != 0x0400) + elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad control: %04x", chan->chcr); + if ((chan->sar & ~0x20000000) != 0x00004012) + elprintf(EL_32XP|EL_ANOMALY, "dreq0: bad sar?: %08x", chan->sar); + + // HACK: assume bus is busy and SH2 is halted + sh2->state |= SH2_STATE_SLEEP; + + for (i = 0; i < Pico32x.dmac0_fifo_ptr && chan->tcr > 0; i++) { + elprintf_sh2(sh2, EL_32XP, "dreq0 [%08x] %04x, dreq_len %d", + chan->dar, Pico32x.dmac_fifo[i], dreqlen); + p32x_sh2_write16(chan->dar, Pico32x.dmac_fifo[i], sh2); + chan->dar += 2; + chan->tcr--; + } + + if (Pico32x.dmac0_fifo_ptr != i) + memmove(Pico32x.dmac_fifo, &Pico32x.dmac_fifo[i], + (Pico32x.dmac0_fifo_ptr - i) * 2); + Pico32x.dmac0_fifo_ptr -= i; + + Pico32x.regs[6 / 2] &= ~P32XS_FULL; + if (chan->tcr == 0) + dmac_transfer_complete(sh2, chan); + else + sh2_end_run(sh2, 16); +} + +static void dreq1_do(SH2 *sh2, struct dma_chan *chan) +{ + // debug/sanity checks + if ((chan->chcr & 0xc308) != 0x0000) + elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad control: %04x", chan->chcr); + if ((chan->dar & ~0xf) != 0x20004030) + elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad dar?: %08x\n", chan->dar); + + dmac_transfer_one(sh2, chan); + if (chan->tcr == 0) + dmac_transfer_complete(sh2, chan); +} + +void p32x_dreq0_trigger(void) +{ + struct dmac *mdmac = (void *)&msh2.peri_regs[0x180 / 4]; + struct dmac *sdmac = (void *)&ssh2.peri_regs[0x180 / 4]; + + elprintf(EL_32XP, "dreq0_trigger"); + if ((mdmac->dmaor & DMA_DME) && (mdmac->chan[0].chcr & 3) == DMA_DE) { + dreq0_do(&msh2, &mdmac->chan[0]); + } + if ((sdmac->dmaor & DMA_DME) && (sdmac->chan[0].chcr & 3) == DMA_DE) { + dreq0_do(&ssh2, &sdmac->chan[0]); + } +} + +void p32x_dreq1_trigger(void) +{ + struct dmac *mdmac = (void *)&msh2.peri_regs[0x180 / 4]; + struct dmac *sdmac = (void *)&ssh2.peri_regs[0x180 / 4]; + int hit = 0; + + elprintf(EL_32XP, "dreq1_trigger"); + if ((mdmac->dmaor & DMA_DME) && (mdmac->chan[1].chcr & 3) == DMA_DE) { + dreq1_do(&msh2, &mdmac->chan[1]); + hit = 1; + } + if ((sdmac->dmaor & DMA_DME) && (sdmac->chan[1].chcr & 3) == DMA_DE) { + dreq1_do(&ssh2, &sdmac->chan[1]); + hit = 1; + } + + // debug +#if (EL_LOGMASK & (EL_32XP|EL_ANOMALY)) + { + static int miss_count; + if (!hit) { + if (++miss_count == 4) + elprintf(EL_32XP|EL_ANOMALY, "dreq1: nobody cared"); + } + else + miss_count = 0; + } +#endif + (void)hit; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cart.c b/waterbox/picodrive/pico/cart.c new file mode 100644 index 0000000000..7a51701c15 --- /dev/null +++ b/waterbox/picodrive/pico/cart.c @@ -0,0 +1,703 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" +#include + +static const uint32_t crc32tab[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, +}; + +uint32_t crc32(const uint8_t *p, size_t size) +{ + uint32_t crc = ~0; + while (size--) + crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xFF]; + return ~crc; +} + + +static int rom_alloc_size; +static const char *rom_exts[] = { "bin", "gen", "smd", "iso", "sms", "gg", "sg" }; + +void (*PicoCartMemSetup)(void); + +void (*PicoCDLoadProgressCB)(const char *fname, int percent) = NULL; // handled in Pico/cd/cd_file.c + +int PicoGameLoaded; + +static void PicoCartDetect(const char *carthw_cfg); + +static const char *get_ext(const char *path) +{ + const char *ext; + if (strlen(path) < 4) + return ""; // no ext + + // allow 2 or 3 char extensions for now + ext = path + strlen(path) - 2; + if (ext[-1] != '.') ext--; + if (ext[-1] != '.') + return ""; + return ext; +} + +// byteswap, data needs to be int aligned, src can match dst +void Byteswap(void *dst, const void *src, int len) +{ + const unsigned int *ps = src; + unsigned int *pd = dst; + int i, m; + + if (len < 2) + return; + + m = 0x00ff00ff; + for (i = 0; i < len / 4; i++) { + unsigned int t = ps[i]; + pd[i] = ((t & m) << 8) | ((t & ~m) >> 8); + } +} + +// Interleve a 16k block and byteswap +static int InterleveBlock(unsigned char *dest,unsigned char *src) +{ + int i=0; + for (i=0;i<0x2000;i++) dest[(i<<1) ]=src[ i]; // Odd + for (i=0;i<0x2000;i++) dest[(i<<1)+1]=src[0x2000+i]; // Even + return 0; +} + +// Decode a SMD file +static int DecodeSmd(unsigned char *data,int len) +{ + unsigned char *temp=NULL; + int i=0; + + temp=(unsigned char *)malloc(0x4000); + if (temp==NULL) return 1; + memset(temp,0,0x4000); + + // Interleve each 16k block and shift down by 0x200: + for (i=0; i+0x4200<=len; i+=0x4000) + { + InterleveBlock(temp,data+0x200+i); // Interleve 16k to temporary buffer + memcpy(data+i,temp,0x4000); // Copy back in + } + + free(temp); + return 0; +} + +static unsigned char *PicoCartAlloc(int filesize, int is_sms) +{ + unsigned char *rom; + + if (is_sms) { + // make size power of 2 for easier banking handling + int s = 0, tmp = filesize; + while ((tmp >>= 1) != 0) + s++; + if (filesize > (1 << s)) + s++; + rom_alloc_size = 1 << s; + // be sure we can cover all address space + if (rom_alloc_size < 0x10000) + rom_alloc_size = 0x10000; + } + else { + // make alloc size at least sizeof(mcd_state), + // in case we want to switch to CD mode + if (filesize < sizeof(mcd_state)) + filesize = sizeof(mcd_state); + + // align to 512K for memhandlers + rom_alloc_size = (filesize + 0x7ffff) & ~0x7ffff; + } + + if (rom_alloc_size - filesize < 4) + rom_alloc_size += 4; // padding for out-of-bound exec protection + + // Allocate space for the rom plus padding + rom = malloc(rom_alloc_size); + return rom; +} + +int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms) +{ + unsigned char *rom; + int size, bytes_read; + + if (f == NULL) + return 1; + + size = f->size; + if (size <= 0) return 1; + size = (size+3)&~3; // Round up to a multiple of 4 + + // Allocate space for the rom plus padding + rom = PicoCartAlloc(size, is_sms); + if (rom == NULL) { + elprintf(EL_STATUS, "out of memory (wanted %i)", size); + return 2; + } + + bytes_read = pm_read(rom,size,f); // Load up the rom + if (bytes_read <= 0) { + elprintf(EL_STATUS, "read failed"); + return 3; + } + + if (!is_sms) + { + // maybe we are loading MegaCD BIOS? + if (!(PicoAHW & PAHW_MCD) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || + !strncmp((char *)rom+0x128, "BOOT", 4))) { + PicoAHW |= PAHW_MCD; + } + + // Check for SMD: + if (size >= 0x4200 && (size&0x3fff) == 0x200 && + ((rom[0x2280] == 'S' && rom[0x280] == 'E') || (rom[0x280] == 'S' && rom[0x2281] == 'E'))) { + elprintf(EL_STATUS, "SMD format detected."); + DecodeSmd(rom,size); size-=0x200; // Decode and byteswap SMD + } + else Byteswap(rom, rom, size); // Just byteswap + } + else + { + if (size >= 0x4200 && (size&0x3fff) == 0x200) { + elprintf(EL_STATUS, "SMD format detected."); + // at least here it's not interleaved + size -= 0x200; + memmove(rom, rom + 0x200, size); + } + } + + if (prom) *prom = rom; + if (psize) *psize = size; + + return 0; +} + +// Insert a cartridge: +int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_cfg) +{ + // notaz: add a 68k "jump one op back" opcode to the end of ROM. + // This will hang the emu, but will prevent nasty crashes. + // note: 4 bytes are padded to every ROM + if (rom != NULL) + *(unsigned long *)(rom+romsize) = 0xFFFE4EFA; // 4EFA FFFE byteswapped + + Pico.rom=rom; + Pico.romsize=romsize; + + if (SRam.data) { + free(SRam.data); + SRam.data = NULL; + } + + PicoAHW &= PAHW_MCD|PAHW_SMS; + + PicoCartMemSetup = NULL; + PicoDmaHook = NULL; + PicoResetHook = NULL; + PicoLineHook = NULL; + + if (!(PicoAHW & (PAHW_MCD|PAHW_SMS))) + PicoCartDetect(carthw_cfg); + + // setup correct memory map for loaded ROM + switch (PicoAHW) { + default: + elprintf(EL_STATUS|EL_ANOMALY, "starting in unknown hw configuration: %x", PicoAHW); + case 0: + case PAHW_SVP: PicoMemSetup(); break; + case PAHW_MCD: PicoMemSetupCD(); break; + case PAHW_PICO: PicoMemSetupPico(); break; + case PAHW_SMS: PicoMemSetupMS(); break; + } + + if (PicoCartMemSetup != NULL) + PicoCartMemSetup(); + + if (PicoAHW & PAHW_SMS) + PicoPowerMS(); + else + PicoPower(); + + PicoGameLoaded = 1; + return 0; +} + +static unsigned int rom_crc32(void) +{ + unsigned int crc; + elprintf(EL_STATUS, "caclulating CRC32.."); + + // have to unbyteswap for calculation.. + Byteswap(Pico.rom, Pico.rom, Pico.romsize); + crc = crc32(Pico.rom, Pico.romsize); + Byteswap(Pico.rom, Pico.rom, Pico.romsize); + return crc; +} + +static int rom_strcmp(int rom_offset, const char *s1) +{ + int i, len = strlen(s1); + const char *s_rom = (const char *)Pico.rom; + if (rom_offset + len > Pico.romsize) + return 0; + for (i = 0; i < len; i++) + if (s1[i] != s_rom[(i + rom_offset) ^ 1]) + return 1; + return 0; +} + +static unsigned int rom_read32(int addr) +{ + unsigned short *m = (unsigned short *)(Pico.rom + addr); + return (m[0] << 16) | m[1]; +} + +static char *sskip(char *s) +{ + while (*s && isspace_(*s)) + s++; + return s; +} + +static void rstrip(char *s) +{ + char *p; + for (p = s + strlen(s) - 1; p >= s; p--) + if (isspace_(*p)) + *p = 0; +} + +static int parse_3_vals(char *p, int *val0, int *val1, int *val2) +{ + char *r; + *val0 = strtoul(p, &r, 0); + if (r == p) + goto bad; + p = sskip(r); + if (*p++ != ',') + goto bad; + *val1 = strtoul(p, &r, 0); + if (r == p) + goto bad; + p = sskip(r); + if (*p++ != ',') + goto bad; + *val2 = strtoul(p, &r, 0); + if (r == p) + goto bad; + + return 1; +bad: + return 0; +} + +static int is_expr(const char *expr, char **pr) +{ + int len = strlen(expr); + char *p = *pr; + + if (strncmp(expr, p, len) != 0) + return 0; + p = sskip(p + len); + if (*p != '=') + return 0; // wrong or malformed + + *pr = sskip(p + 1); + return 1; +} + +#include "carthw_cfg.c" + +static void parse_carthw(const char *carthw_cfg, int *fill_sram) +{ + int line = 0, any_checks_passed = 0, skip_sect = 0; + const char *s, *builtin = builtin_carthw_cfg; + int tmp, rom_crc = 0; + char buff[256], *p, *r; + FILE *f; + + f = fopen(carthw_cfg, "r"); + if (f == NULL) + f = fopen("pico/carthw.cfg", "r"); + if (f == NULL) + elprintf(EL_STATUS, "couldn't open carthw.cfg!"); + + for (;;) + { + if (f != NULL) { + p = fgets(buff, sizeof(buff), f); + if (p == NULL) + break; + } + else { + if (*builtin == 0) + break; + for (s = builtin; *s != 0 && *s != '\n'; s++) + ; + while (*s == '\n') + s++; + tmp = s - builtin; + if (tmp > sizeof(buff) - 1) + tmp = sizeof(buff) - 1; + memcpy(buff, builtin, tmp); + buff[tmp] = 0; + p = buff; + builtin = s; + } + + line++; + p = sskip(p); + if (*p == 0 || *p == '#') + continue; + + if (*p == '[') { + any_checks_passed = 0; + skip_sect = 0; + continue; + } + + if (skip_sect) + continue; + + /* look for checks */ + if (is_expr("check_str", &p)) + { + int offs; + offs = strtoul(p, &r, 0); + if (offs < 0 || offs > Pico.romsize) { + elprintf(EL_STATUS, "carthw:%d: check_str offs out of range: %d\n", line, offs); + goto bad; + } + p = sskip(r); + if (*p != ',') + goto bad; + p = sskip(p + 1); + if (*p != '"') + goto bad; + p++; + r = strchr(p, '"'); + if (r == NULL) + goto bad; + *r = 0; + + if (rom_strcmp(offs, p) == 0) + any_checks_passed = 1; + else + skip_sect = 1; + continue; + } + else if (is_expr("check_size_gt", &p)) + { + int size; + size = strtoul(p, &r, 0); + if (r == p || size < 0) + goto bad; + + if (Pico.romsize > size) + any_checks_passed = 1; + else + skip_sect = 1; + continue; + } + else if (is_expr("check_csum", &p)) + { + int csum; + csum = strtoul(p, &r, 0); + if (r == p || (csum & 0xffff0000)) + goto bad; + + if (csum == (rom_read32(0x18c) & 0xffff)) + any_checks_passed = 1; + else + skip_sect = 1; + continue; + } + else if (is_expr("check_crc32", &p)) + { + unsigned int crc; + crc = strtoul(p, &r, 0); + if (r == p) + goto bad; + + if (rom_crc == 0) + rom_crc = rom_crc32(); + if (crc == rom_crc) + any_checks_passed = 1; + else + skip_sect = 1; + continue; + } + + /* now time for actions */ + if (is_expr("hw", &p)) { + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + if (strcmp(p, "svp") == 0) + PicoSVPStartup(); + else if (strcmp(p, "pico") == 0) + PicoInitPico(); + else if (strcmp(p, "prot") == 0) + carthw_sprot_startup(); + else if (strcmp(p, "ssf2_mapper") == 0) + carthw_ssf2_startup(); + else if (strcmp(p, "x_in_1_mapper") == 0) + carthw_Xin1_startup(); + else if (strcmp(p, "realtec_mapper") == 0) + carthw_realtec_startup(); + else if (strcmp(p, "radica_mapper") == 0) + carthw_radica_startup(); + else if (strcmp(p, "piersolar_mapper") == 0) + carthw_pier_startup(); + else if (strcmp(p, "prot_lk3") == 0) + carthw_prot_lk3_startup(); + else { + elprintf(EL_STATUS, "carthw:%d: unsupported mapper: %s", line, p); + skip_sect = 1; + } + continue; + } + if (is_expr("sram_range", &p)) { + int start, end; + + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + start = strtoul(p, &r, 0); + if (r == p) + goto bad; + p = sskip(r); + if (*p != ',') + goto bad; + p = sskip(p + 1); + end = strtoul(p, &r, 0); + if (r == p) + goto bad; + if (((start | end) & 0xff000000) || start > end) { + elprintf(EL_STATUS, "carthw:%d: bad sram_range: %08x - %08x", line, start, end); + goto bad_nomsg; + } + SRam.start = start; + SRam.end = end; + continue; + } + else if (is_expr("prop", &p)) { + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + if (strcmp(p, "no_sram") == 0) + SRam.flags &= ~SRF_ENABLED; + else if (strcmp(p, "no_eeprom") == 0) + SRam.flags &= ~SRF_EEPROM; + else if (strcmp(p, "filled_sram") == 0) + *fill_sram = 1; + else if (strcmp(p, "force_6btn") == 0) + PicoQuirks |= PQUIRK_FORCE_6BTN; + else { + elprintf(EL_STATUS, "carthw:%d: unsupported prop: %s", line, p); + goto bad_nomsg; + } + elprintf(EL_STATUS, "game prop: %s", p); + continue; + } + else if (is_expr("eeprom_type", &p)) { + int type; + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + type = strtoul(p, &r, 0); + if (r == p || type < 0) + goto bad; + SRam.eeprom_type = type; + SRam.flags |= SRF_EEPROM; + continue; + } + else if (is_expr("eeprom_lines", &p)) { + int scl, sda_in, sda_out; + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + if (!parse_3_vals(p, &scl, &sda_in, &sda_out)) + goto bad; + if (scl < 0 || scl > 15 || sda_in < 0 || sda_in > 15 || + sda_out < 0 || sda_out > 15) + goto bad; + + SRam.eeprom_bit_cl = scl; + SRam.eeprom_bit_in = sda_in; + SRam.eeprom_bit_out= sda_out; + continue; + } + else if ((tmp = is_expr("prot_ro_value16", &p)) || is_expr("prot_rw_value16", &p)) { + int addr, mask, val; + if (!any_checks_passed) + goto no_checks; + rstrip(p); + + if (!parse_3_vals(p, &addr, &mask, &val)) + goto bad; + + carthw_sprot_new_location(addr, mask, val, tmp ? 1 : 0); + continue; + } + + +bad: + elprintf(EL_STATUS, "carthw:%d: unrecognized expression: %s", line, buff); +bad_nomsg: + skip_sect = 1; + continue; + +no_checks: + elprintf(EL_STATUS, "carthw:%d: command without any checks before it: %s", line, buff); + skip_sect = 1; + continue; + } + + if (f != NULL) + fclose(f); +} + +/* + * various cart-specific things, which can't be handled by generic code + */ +static void PicoCartDetect(const char *carthw_cfg) +{ + int fill_sram = 0; + + memset(&SRam, 0, sizeof(SRam)); + if (Pico.rom[0x1B1] == 'R' && Pico.rom[0x1B0] == 'A') + { + SRam.start = rom_read32(0x1B4) & ~0xff000001; // align + SRam.end = (rom_read32(0x1B8) & ~0xff000000) | 1; + if (Pico.rom[0x1B2] & 0x40) + // EEPROM + SRam.flags |= SRF_EEPROM; + SRam.flags |= SRF_ENABLED; + } + if (SRam.end == 0 || SRam.start > SRam.end) + { + // some games may have bad headers, like S&K and Sonic3 + // note: majority games use 0x200000 as starting address, but there are some which + // use something else (0x300000 by HardBall '95). Luckily they have good headers. + SRam.start = 0x200000; + SRam.end = 0x203FFF; + SRam.flags |= SRF_ENABLED; + } + + // set EEPROM defaults, in case it gets detected + SRam.eeprom_type = 0; // 7bit (24C01) + SRam.eeprom_bit_cl = 1; + SRam.eeprom_bit_in = 0; + SRam.eeprom_bit_out= 0; + + if (carthw_cfg != NULL) + parse_carthw(carthw_cfg, &fill_sram); + + if (SRam.flags & SRF_ENABLED) + { + if (SRam.flags & SRF_EEPROM) + SRam.size = 0x2000; + else + SRam.size = SRam.end - SRam.start + 1; + + SRam.data = calloc(SRam.size, 1); + if (SRam.data == NULL) + SRam.flags &= ~SRF_ENABLED; + + if (SRam.eeprom_type == 1) // 1 == 0 in PD EEPROM code + SRam.eeprom_type = 0; + } + + if ((SRam.flags & SRF_ENABLED) && fill_sram) + { + elprintf(EL_STATUS, "SRAM fill"); + memset(SRam.data, 0xff, SRam.size); + } + + // Unusual region 'code' + if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0) + *(int *) (Pico.rom + 0x1f0) = 0x20204520; +} diff --git a/waterbox/picodrive/pico/carthw.cfg b/waterbox/picodrive/pico/carthw.cfg new file mode 100644 index 0000000000..72d4a9a158 --- /dev/null +++ b/waterbox/picodrive/pico/carthw.cfg @@ -0,0 +1,320 @@ +# hardware (hw = ...): +# svp - Sega Virtua Processor +# pico - Sega Pico (not really cart hw, but convenient to support here) +# prot - siple copy protection devices in unlicensed cartridges (see prot. below) +# prot_lk3 - Lion King 3 / Super King Kong 99 protection. +# +# cartridge properties (prop = ...): +# no_sram - don't emulate sram/EEPROM even if ROM headers tell it's there +# no_eeprom - save storage is not EEPROM, even if ROM headers tell it is +# filled_sram - save storage needs to be initialized with FFh instead of 00h +# force_6btn - game only supports 6 button pad (32X X-men proto) +# +# mappers (hw = ...): +# ssf2_mapper - used in Super Street Fighter2 +# x_in_1_mapper - used in many *-in-1 pirate carts +# realtec_mapper +# radica_mapper - similar to x_in_1_mapper +# piersolar_mapper - used in Pier Solar +# +# save storage memory range (inclusive, overrides ROM header): +# sram_range = +# +# EEPROM: +# eeprom_type = <1|2|3> - enable EEPROM, use type X (7bit, 2 addr words, 3 addr words). +# See EkeEke's gen_eeprom.pdf "mode" descriptions for 24Cxx EEPROMs. +# eeprom_lines = +# - select data bus pins that are connected to EEPROM +# SCL, SDA_IN and SDA_OUT pins (0-15 for D0-D15). +# hw = prot: +# prot_ro_value16 = - return constant on reads at location +# ( & ), ignore writes. +# prot_rw_value16 = - same as above, but writeable + +[Virtua Racing - SVP] +check_str = 0x150, "Virtua Racing" +check_str = 0x810, "OHMP" +hw = svp + +[Virtua Racing - SVP] +check_str = 0x150, "VIRTUA RACING" +check_str = 0x810, "OHMP" +hw = svp + +[Pico] +check_str = 0x100, "SEGA PICO" +hw = pico + +[Pico] +check_str = 0x100, "IMA IKUNOUJYUKU" +hw = pico + +# sram emulation triggers some protection for this one +[Puggsy] +check_str = 0x120, "PUGGSY" +prop = no_sram + +# game has problems if it's save RAM is not initialized with FFh: +[Dino Dini's Soccer] +check_str = 0x150, "DINO DINI'S SOCCER" +prop = filled_sram + +[Micro Machines 2 - Turbo Tournament] +check_str = 0x150, "MICRO MACHINES II" +prop = filled_sram + +# X-Men proto +[X-Men (prototype)] +check_str = 0x150, "32X SAMPLE PROGRAM" +check_str = 0x32b74c, "Bishop Level" +prop = force_6btn + +# The SSF2 mapper +[Super Street Fighter II - The New Challengers (U)] +check_str = 0x150, "SUPER STREET FIGHTER2 The New Challengers" +hw = ssf2_mapper +prop = no_sram + +# The Pier Solar mapper, custom eeprom location +[Pier Solar and the Great Architects] +check_str = 0x150, "PIER" +check_str = 0x610, "Respect" +hw = piersolar_mapper + +# detect *_in_1 based on first game and if it's larger than it should be, +# as some dumps look like to be incomplete. +# This will also pick overdumps, but those should still work with the mapper applied. +[12-in-1 (Unl)] +check_str = 0x120, "FLICKY" +check_size_gt = 0x020000 +hw = x_in_1_mapper + +[4-in-1] +check_str = 0x150, "ROBOCOP 3" +check_size_gt = 0x080000 +hw = x_in_1_mapper + +[4-in-1 a1] +check_str = 0x150, "ALIEN 3" +check_size_gt = 0x080000 +hw = x_in_1_mapper + +[Super 15-in-1] +check_str = 0x150, " SHOVE IT!" +check_size_gt = 0x020000 +hw = x_in_1_mapper + +[Super 19-in-1] +check_str = 0x150, "MS PACMAN" +check_size_gt = 0x020000 +hw = x_in_1_mapper + +# radica +[radica_v1] +check_str = 0x150, "KID CHAMELEON" +check_size_gt = 0x100000 +hw = radica_mapper + +# realtec +[Earth Defend, The (Unl)] +check_str = 0x94, "THE EARTH DEFEND" +hw = realtec_mapper + +[Funny World & Balloon Boy (Unl)] +check_str = 0xfe, "WISEGAME 11-03-1993" +hw = realtec_mapper + +[Whac-A-Critter (Unl)] +check_str = 0x95, "MALLET LEGEND" +hw = realtec_mapper + +# EEPROM games - thanks to EkeEke for most of this info +[College Slam] +check_str = 0x150, "COLLEGE SLAM" +eeprom_type = 3 +eeprom_lines = 8,0,0 + +[Frank Thomas Big Hurt Baseball] +check_str = 0x150, "FRANK THOMAS BIGHURT BASEBAL" +eeprom_type = 3 +eeprom_lines = 8,0,0 + +[MICRO MACHINES II] +check_str = 0x150, "MICRO MACHINES II" +sram_range = 0x300000,0x380001 +eeprom_type = 2 +eeprom_lines = 9,8,7 + +[Micro Machines - Turbo Tournament '96] +check_str = 0x150, " " +check_csum = 0x165e +sram_range = 0x300000,0x380001 +eeprom_type = 2 +eeprom_lines = 9,8,7 + +[Micro Machines - Turbo Tournament '96] +check_str = 0x150, " " +check_csum = 0x2c41 +sram_range = 0x300000,0x380001 +eeprom_type = 2 +eeprom_lines = 9,8,7 + +[Micro Machines Military] +check_str = 0x150, " " +check_csum = 0x168b +sram_range = 0x300000,0x380001 +eeprom_type = 2 +eeprom_lines = 9,8,7 + +[Micro Machines Military] +check_str = 0x150, " " +check_csum = 0xcee0 +sram_range = 0x300000,0x380001 +eeprom_type = 2 +eeprom_lines = 9,8,7 + +[NBA Jam] +check_str = 0x150, "NBA JAM " +eeprom_type = 2 +eeprom_lines = 1,0,1 + +[NBA Jam Tournament Edition] +check_str = 0x150, "NBA JAM TOURNAMENT EDITION" +sram_range = 0x200000,0x200001 +eeprom_type = 2 +eeprom_lines = 8,0,0 + +[NFL Quarterback Club] +check_str = 0x150, "NFL QUARTERBACK CLUB" +eeprom_type = 2 +eeprom_lines = 8,0,0 + +[NHLPA Hockey '93] +check_str = 0x150, "NHLPA Hockey '93" +sram_range = 0x200000,0x200001 +eeprom_type = 1 +eeprom_lines = 6,7,7 + +[NHLPA Hockey '93] +check_str = 0x150, "NHLPA HOCKEY '93" +sram_range = 0x200000,0x200001 +eeprom_type = 1 +eeprom_lines = 6,7,7 + +[Rings of Power] +check_str = 0x150, "RINGS OF POWER" +sram_range = 0x200000,0x200001 +eeprom_type = 1 +eeprom_lines = 6,7,7 + +# Unlicensed games with simple protections +# some of these come from Haze, some from myself (notaz). +[Bug's Life, A (Unl)] +check_str = 0x104, " " +check_crc32 = 0x10458e09 +hw = prot +prot_ro_value16 = 0xa13000,0xffff00,0x28 + +[Elf Wor (Unl)] +check_str = 0x172, "GAME : ELF WOR" +hw = prot +prot_ro_value16 = 0x400000,-2,0x5500 +prot_ro_value16 = 0x400002,-2,0xc900 # check is done if the above one fails +prot_ro_value16 = 0x400004,-2,0x0f00 +prot_ro_value16 = 0x400006,-2,0x1800 # similar to above + +[King of Fighters '98, The (Unl)] +check_str = 0x104, " " +check_crc32 = 0xcbc38eea +hw = prot +prot_ro_value16 = 0x480000,0xff0000,0xaa00 +prot_ro_value16 = 0x4a0000,0xff0000,0x0a00 +prot_ro_value16 = 0x4c0000,0xff0000,0xf000 +prot_ro_value16 = 0x400000,0xc00000,0x0000 # default for 400000-7f0000 + +[Lion King 3 (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0xc004219d +hw = prot_lk3 + +[Lion King II, The (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0xaff46765 +hw = prot +prot_rw_value16 = 0x400000,0xc00004,0 +prot_rw_value16 = 0x400004,0xc00004,0 + +[Mahjong Lover (Unl)] +check_str = 0x118, "CREATON. " +check_crc32 = 0xddd02ba4 +hw = prot +prot_ro_value16 = 0x400000,-2,0x9000 +prot_ro_value16 = 0x401000,-2,0xd300 + +[Pocket Monsters (Unl)] +check_str = 0x104, " " +check_crc32 = 0xf68f6367 +hw = prot +prot_ro_value16 = 0xa13002,-2,0x01 +prot_ro_value16 = 0xa1303e,-2,0x1f + +[Pocket Monsters (Unl) [a1]] +check_str = 0x104, " " +check_crc32 = 0xfb176667 +hw = prot +prot_ro_value16 = 0xa13000,-2,0x14 +prot_ro_value16 = 0xa13002,-2,0x01 +prot_ro_value16 = 0xa1303e,-2,0x1f + +[Rockman X3 (Unl)] +check_csum = 0 +check_crc32 = 0x3ee639f0 +hw = prot +prot_ro_value16 = 0xa13000,-2,0x0c + +[Smart Mouse (Unl)] +check_csum = 0 +check_crc32 = 0xdecdf740 +hw = prot +prot_ro_value16 = 0x400000,-2,0x5500 +prot_ro_value16 = 0x400002,-2,0x0f00 +prot_ro_value16 = 0x400004,-2,0xaa00 +prot_ro_value16 = 0x400006,-2,0xf000 + +[Soul Blade (Unl)] +check_str = 0x104, " " +check_crc32 = 0xf26f88d1 +hw = prot +prot_ro_value16 = 0x400002,-2,0x9800 +prot_ro_value16 = 0x400004,-2,0xaa00 # or 0xc900 +prot_ro_value16 = 0x400006,-2,0xf000 + +[Super Bubble Bobble (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0x4820a161 +hw = prot +prot_ro_value16 = 0x400000,-2,0x5500 +prot_ro_value16 = 0x400002,-2,0x0f00 + +[Super King Kong 99 (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0x413dfee2 +hw = prot_lk3 + +[Super Mario Bros. (Unl)] +check_str = 0x140, "SUPER MARIO BROS " +hw = prot +prot_ro_value16 = 0xa13000,-2,0x0c + +[Super Mario 2 1998 (Unl)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0xf7e1b3e1 +hw = prot +prot_ro_value16 = 0xa13000,-2,0x0a + +[Squirrel King (R)] +check_str = 0x104, " are Registered Trademarks" +check_crc32 = 0xb8261ff5 +hw = prot +prot_rw_value16 = 0x400000,0xc00000,0 + diff --git a/waterbox/picodrive/pico/carthw/carthw.c b/waterbox/picodrive/pico/carthw/carthw.c new file mode 100644 index 0000000000..1719e8b0ad --- /dev/null +++ b/waterbox/picodrive/pico/carthw/carthw.c @@ -0,0 +1,629 @@ +/* + * Support for a few cart mappers and some protection. + * (C) notaz, 2008-2011 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" +#include "../memory.h" + + +/* The SSFII mapper */ +static unsigned char ssf2_banks[8]; + +static void carthw_ssf2_write8(u32 a, u32 d) +{ + u32 target, base; + + if ((a & 0xfffff0) != 0xa130f0) { + PicoWrite8_io(a, d); + return; + } + + a &= 0x0e; + if (a == 0) + return; + + ssf2_banks[a >> 1] = d; + base = d << 19; + target = a << 18; + if (base + 0x80000 > Pico.romsize) { + elprintf(EL_ANOMALY|EL_STATUS, "ssf2: missing bank @ %06x", base); + return; + } + + cpu68k_map_set(m68k_read8_map, target, target + 0x80000 - 1, Pico.rom + base, 0); + cpu68k_map_set(m68k_read16_map, target, target + 0x80000 - 1, Pico.rom + base, 0); +} + +static void carthw_ssf2_mem_setup(void) +{ + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_ssf2_write8, 1); +} + +void carthw_ssf2_startup(void) +{ + int i; + + elprintf(EL_STATUS, "SSF2 mapper startup"); + + // default map + for (i = 0; i < 8; i++) + ssf2_banks[i] = i; + + PicoCartMemSetup = carthw_ssf2_mem_setup; +} + + +/* Common *-in-1 pirate mapper. + * Switches banks based on addr lines when /TIME is set. + * TODO: verify + */ +static unsigned int carthw_Xin1_baddr = 0; + +static void carthw_Xin1_do(u32 a, int mask, int shift) +{ + int len; + + carthw_Xin1_baddr = a; + a &= mask; + a <<= shift; + len = Pico.romsize - a; + if (len <= 0) { + elprintf(EL_ANOMALY|EL_STATUS, "X-in-1: missing bank @ %06x", a); + return; + } + + len = (len + M68K_BANK_MASK) & ~M68K_BANK_MASK; + cpu68k_map_set(m68k_read8_map, 0x000000, len - 1, Pico.rom + a, 0); + cpu68k_map_set(m68k_read16_map, 0x000000, len - 1, Pico.rom + a, 0); +} + +// TODO: test a0, reads, w16 +static void carthw_Xin1_write8(u32 a, u32 d) +{ + if ((a & 0xffff00) != 0xa13000) { + PicoWrite8_io(a, d); + return; + } + + carthw_Xin1_do(a, 0x3f, 16); +} + +static void carthw_Xin1_mem_setup(void) +{ + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_Xin1_write8, 1); +} + +static void carthw_Xin1_reset(void) +{ + carthw_Xin1_write8(0xa13000, 0); +} + +void carthw_Xin1_startup(void) +{ + elprintf(EL_STATUS, "X-in-1 mapper startup"); + + PicoCartMemSetup = carthw_Xin1_mem_setup; + PicoResetHook = carthw_Xin1_reset; +} + + +/* Realtec, based on TascoDLX doc + * http://www.sharemation.com/TascoDLX/REALTEC%20Cart%20Mapper%20-%20description%20v1.txt + */ +static int realtec_bank = 0x80000000, realtec_size = 0x80000000; + +static void carthw_realtec_write8(u32 a, u32 d) +{ + int i, bank_old = realtec_bank, size_old = realtec_size; + + if (a == 0x400000) + { + realtec_bank &= 0x0e0000; + realtec_bank |= 0x300000 & (d << 19); + if (realtec_bank != bank_old) + elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc); + } + else if (a == 0x402000) + { + realtec_size = (d << 17) & 0x3e0000; + if (realtec_size != size_old) + elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc); + } + else if (a == 0x404000) + { + realtec_bank &= 0x300000; + realtec_bank |= 0x0e0000 & (d << 17); + if (realtec_bank != bank_old) + elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc); + } + else + elprintf(EL_ANOMALY, "realtec: unexpected write [%06x] %02x @ %06x", a, d, SekPc); + + if (realtec_bank >= 0 && realtec_size >= 0 && + (realtec_bank != bank_old || realtec_size != size_old)) + { + elprintf(EL_ANOMALY, "realtec: new bank %06x, size %06x", realtec_bank, realtec_size, SekPc); + if (realtec_size > Pico.romsize - realtec_bank) + { + elprintf(EL_ANOMALY, "realtec: bank too large / out of range?"); + return; + } + + for (i = 0; i < 0x400000; i += realtec_size) { + cpu68k_map_set(m68k_read8_map, i, realtec_size - 1, Pico.rom + realtec_bank, 0); + cpu68k_map_set(m68k_read16_map, i, realtec_size - 1, Pico.rom + realtec_bank, 0); + } + } +} + +static void carthw_realtec_reset(void) +{ + int i; + + /* map boot code */ + for (i = 0; i < 0x400000; i += M68K_BANK_SIZE) { + cpu68k_map_set(m68k_read8_map, i, i + M68K_BANK_SIZE - 1, Pico.rom + Pico.romsize, 0); + cpu68k_map_set(m68k_read16_map, i, i + M68K_BANK_SIZE - 1, Pico.rom + Pico.romsize, 0); + } + cpu68k_map_set(m68k_write8_map, 0x400000, 0x400000 + M68K_BANK_SIZE - 1, carthw_realtec_write8, 1); + realtec_bank = realtec_size = 0x80000000; +} + +void carthw_realtec_startup(void) +{ + int i; + + elprintf(EL_STATUS, "Realtec mapper startup"); + + // allocate additional bank for boot code + // (we know those ROMs have aligned size) + i = PicoCartResize(Pico.romsize + M68K_BANK_SIZE); + if (i != 0) { + elprintf(EL_STATUS, "OOM"); + return; + } + + // create bank for boot code + for (i = 0; i < M68K_BANK_SIZE; i += 0x2000) + memcpy(Pico.rom + Pico.romsize + i, Pico.rom + Pico.romsize - 0x2000, 0x2000); + + PicoResetHook = carthw_realtec_reset; +} + +/* Radica mapper, based on DevSter's info + * http://devster.monkeeh.com/sega/radica/ + * XXX: mostly the same as X-in-1, merge? + */ +static u32 carthw_radica_read16(u32 a) +{ + if ((a & 0xffff00) != 0xa13000) + return PicoRead16_io(a); + + carthw_Xin1_do(a, 0x7e, 15); + + return 0; +} + +static void carthw_radica_mem_setup(void) +{ + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, carthw_radica_read16, 1); +} + +static void carthw_radica_reset(void) +{ + carthw_radica_read16(0xa13000); +} + +void carthw_radica_startup(void) +{ + elprintf(EL_STATUS, "Radica mapper startup"); + + PicoCartMemSetup = carthw_radica_mem_setup; + PicoResetHook = carthw_radica_reset; +} + + +/* Pier Solar. Based on my own research */ +static unsigned char pier_regs[8]; +static unsigned char pier_dump_prot; + +static void carthw_pier_write8(u32 a, u32 d) +{ + u32 a8, target, base; + + if ((a & 0xffff00) != 0xa13000) { + PicoWrite8_io(a, d); + return; + } + + a8 = a & 0x0f; + pier_regs[a8 / 2] = d; + + elprintf(EL_UIO, "pier w8 [%06x] %02x @%06x", a, d & 0xffff, SekPc); + switch (a8) { + case 0x01: + break; + case 0x03: + if (!(pier_regs[0] & 2)) + goto unmapped; + target = 0x280000; + base = d << 19; + goto do_map; + case 0x05: + if (!(pier_regs[0] & 2)) + goto unmapped; + target = 0x300000; + base = d << 19; + goto do_map; + case 0x07: + if (!(pier_regs[0] & 2)) + goto unmapped; + target = 0x380000; + base = d << 19; + goto do_map; + case 0x09: + // TODO + break; + case 0x0b: + // eeprom read + default: + unmapped: + //elprintf(EL_UIO, "pier w8 [%06x] %02x @%06x", a, d & 0xffff, SekPc); + elprintf(EL_STATUS, "-- unmapped w8 [%06x] %02x @%06x", a, d & 0xffff, SekPc); + break; + } + return; + +do_map: + if (base + 0x80000 > Pico.romsize) { + elprintf(EL_ANOMALY|EL_STATUS, "pier: missing bank @ %06x", base); + return; + } + cpu68k_map_set(m68k_read8_map, target, target + 0x80000 - 1, Pico.rom + base, 0); + cpu68k_map_set(m68k_read16_map, target, target + 0x80000 - 1, Pico.rom + base, 0); +} + +static void carthw_pier_write16(u32 a, u32 d) +{ + if ((a & 0xffff00) != 0xa13000) { + PicoWrite16_io(a, d); + return; + } + + elprintf(EL_UIO, "pier w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + carthw_pier_write8(a + 1, d); +} + +static u32 carthw_pier_read8(u32 a) +{ + if ((a & 0xffff00) != 0xa13000) + return PicoRead8_io(a); + + if (a == 0xa1300b) + return 0; // TODO + + elprintf(EL_UIO, "pier r8 [%06x] @%06x", a, SekPc); + return 0; +} + +static void carthw_pier_statef(void); + +static u32 carthw_pier_prot_read8(u32 a) +{ + /* it takes more than just these reads here to disable ROM protection, + * but for game emulation purposes this is enough. */ + if (pier_dump_prot > 0) + pier_dump_prot--; + if (pier_dump_prot == 0) { + carthw_pier_statef(); + elprintf(EL_STATUS, "prot off on r8 @%06x", SekPc); + } + elprintf(EL_UIO, "pier r8 [%06x] @%06x", a, SekPc); + + return Pico.rom[(a & 0x7fff) ^ 1]; +} + +static void carthw_pier_mem_setup(void) +{ + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, carthw_pier_write8, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, carthw_pier_write16, 1); + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, carthw_pier_read8, 1); +} + +static void carthw_pier_prot_mem_setup(int prot_enable) +{ + if (prot_enable) { + /* the dump protection.. */ + int a; + for (a = 0x000000; a < 0x400000; a += M68K_BANK_SIZE) { + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, Pico.rom + Pico.romsize, 0); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, Pico.rom + Pico.romsize, 0); + } + cpu68k_map_set(m68k_read8_map, M68K_BANK_SIZE, M68K_BANK_SIZE * 2 - 1, + carthw_pier_prot_read8, 1); + } + else { + cpu68k_map_set(m68k_read8_map, 0, 0x27ffff, Pico.rom, 0); + cpu68k_map_set(m68k_read16_map, 0, 0x27ffff, Pico.rom, 0); + } +} + +static void carthw_pier_statef(void) +{ + carthw_pier_prot_mem_setup(pier_dump_prot); + + if (!pier_dump_prot) { + /* setup all banks */ + u32 r0 = pier_regs[0]; + carthw_pier_write8(0xa13001, 3); + carthw_pier_write8(0xa13003, pier_regs[1]); + carthw_pier_write8(0xa13005, pier_regs[2]); + carthw_pier_write8(0xa13007, pier_regs[3]); + carthw_pier_write8(0xa13001, r0); + } +} + +static void carthw_pier_reset(void) +{ + pier_regs[0] = 1; + pier_regs[1] = pier_regs[2] = pier_regs[3] = 0; + pier_dump_prot = 3; + carthw_pier_statef(); +} + +void carthw_pier_startup(void) +{ + int i; + + elprintf(EL_STATUS, "Pier Solar mapper startup"); + + // mostly same as for realtec.. + i = PicoCartResize(Pico.romsize + M68K_BANK_SIZE); + if (i != 0) { + elprintf(EL_STATUS, "OOM"); + return; + } + + // create dump protection bank + for (i = 0; i < M68K_BANK_SIZE; i += 0x8000) + memcpy(Pico.rom + Pico.romsize + i, Pico.rom, 0x8000); + + PicoCartMemSetup = carthw_pier_mem_setup; + PicoResetHook = carthw_pier_reset; +} + +/* Simple unlicensed ROM protection emulation */ +static struct { + u32 addr; + u32 mask; + u16 val; + u16 readonly; +} *sprot_items; +static int sprot_item_alloc; +static int sprot_item_count; + +static u16 *carthw_sprot_get_val(u32 a, int rw_only) +{ + int i; + + for (i = 0; i < sprot_item_count; i++) + if ((a & sprot_items[i].mask) == sprot_items[i].addr) + if (!rw_only || !sprot_items[i].readonly) + return &sprot_items[i].val; + + return NULL; +} + +static u32 PicoRead8_sprot(u32 a) +{ + u16 *val; + u32 d; + + if (0xa10000 <= a && a < 0xa12000) + return PicoRead8_io(a); + + val = carthw_sprot_get_val(a, 0); + if (val != NULL) { + d = *val; + if (!(a & 1)) + d >>= 8; + elprintf(EL_UIO, "prot r8 [%06x] %02x @%06x", a, d, SekPc); + return d; + } + else { + elprintf(EL_UIO, "prot r8 [%06x] MISS @%06x", a, SekPc); + return 0; + } +} + +static u32 PicoRead16_sprot(u32 a) +{ + u16 *val; + + if (0xa10000 <= a && a < 0xa12000) + return PicoRead16_io(a); + + val = carthw_sprot_get_val(a, 0); + if (val != NULL) { + elprintf(EL_UIO, "prot r16 [%06x] %04x @%06x", a, *val, SekPc); + return *val; + } + else { + elprintf(EL_UIO, "prot r16 [%06x] MISS @%06x", a, SekPc); + return 0; + } +} + +static void PicoWrite8_sprot(u32 a, u32 d) +{ + u16 *val; + + if (0xa10000 <= a && a < 0xa12000) { + PicoWrite8_io(a, d); + return; + } + + val = carthw_sprot_get_val(a, 1); + if (val != NULL) { + if (a & 1) + *val = (*val & 0xff00) | (d | 0xff); + else + *val = (*val & 0x00ff) | (d << 8); + elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + } + else + elprintf(EL_UIO, "prot w8 [%06x] %02x MISS @%06x", a, d & 0xff, SekPc); +} + +static void PicoWrite16_sprot(u32 a, u32 d) +{ + u16 *val; + + if (0xa10000 <= a && a < 0xa12000) { + PicoWrite16_io(a, d); + return; + } + + val = carthw_sprot_get_val(a, 1); + if (val != NULL) { + *val = d; + elprintf(EL_UIO, "prot w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); + } + else + elprintf(EL_UIO, "prot w16 [%06x] %04x MISS @%06x", a, d & 0xffff, SekPc); +} + +void carthw_sprot_new_location(unsigned int a, unsigned int mask, unsigned short val, int is_ro) +{ + if (sprot_items == NULL) { + sprot_items = calloc(8, sizeof(sprot_items[0])); + sprot_item_alloc = 8; + sprot_item_count = 0; + } + + if (sprot_item_count == sprot_item_alloc) { + void *tmp; + sprot_item_alloc *= 2; + tmp = realloc(sprot_items, sprot_item_alloc); + if (tmp == NULL) { + elprintf(EL_STATUS, "OOM"); + return; + } + sprot_items = tmp; + } + + sprot_items[sprot_item_count].addr = a; + sprot_items[sprot_item_count].mask = mask; + sprot_items[sprot_item_count].val = val; + sprot_items[sprot_item_count].readonly = is_ro; + sprot_item_count++; +} + +static void carthw_sprot_mem_setup(void) +{ + int start; + + // map ROM - 0x7fffff, /TIME areas (which are tipically used) + start = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK; + cpu68k_map_set(m68k_read8_map, start, 0x7fffff, PicoRead8_sprot, 1); + cpu68k_map_set(m68k_read16_map, start, 0x7fffff, PicoRead16_sprot, 1); + cpu68k_map_set(m68k_write8_map, start, 0x7fffff, PicoWrite8_sprot, 1); + cpu68k_map_set(m68k_write16_map, start, 0x7fffff, PicoWrite16_sprot, 1); + + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_sprot, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_sprot, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_sprot, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_sprot, 1); +} + +void carthw_sprot_startup(void) +{ + elprintf(EL_STATUS, "Prot emu startup"); + + PicoCartMemSetup = carthw_sprot_mem_setup; +} + +/* Protection emulation for Lion King 3. Credits go to Haze */ +static u8 prot_lk3_cmd, prot_lk3_data; + +static u32 PicoRead8_plk3(u32 a) +{ + u32 d = 0; + switch (prot_lk3_cmd) { + case 1: d = prot_lk3_data >> 1; break; + case 2: // nibble rotate + d = ((prot_lk3_data >> 4) | (prot_lk3_data << 4)) & 0xff; + break; + case 3: // bit rotate + d = prot_lk3_data; + d = (d >> 4) | (d << 4); + d = ((d & 0xcc) >> 2) | ((d & 0x33) << 2); + d = ((d & 0xaa) >> 1) | ((d & 0x55) << 1); + break; +/* Top Fighter 2000 MK VIII (Unl) + case 0x98: d = 0x50; break; // prot_lk3_data == a8 here + case 0x67: d = 0xde; break; // prot_lk3_data == 7b here (rot!) + case 0xb5: d = 0x9f; break; // prot_lk3_data == 4a +*/ + default: + elprintf(EL_UIO, "unhandled prot cmd %02x @%06x", prot_lk3_cmd, SekPc); + break; + } + + elprintf(EL_UIO, "prot r8 [%06x] %02x @%06x", a, d, SekPc); + return d; +} + +static void PicoWrite8_plk3p(u32 a, u32 d) +{ + elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + if (a & 2) + prot_lk3_cmd = d; + else + prot_lk3_data = d; +} + +static void PicoWrite8_plk3b(u32 a, u32 d) +{ + int addr; + + elprintf(EL_UIO, "prot w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + addr = d << 15; + if (addr + 0x8000 > Pico.romsize) { + elprintf(EL_UIO|EL_ANOMALY, "prot_lk3: bank too large: %02x", d); + return; + } + if (addr == 0) + memcpy(Pico.rom, Pico.rom + Pico.romsize, 0x8000); + else + memcpy(Pico.rom, Pico.rom + addr, 0x8000); +} + +static void carthw_prot_lk3_mem_setup(void) +{ + cpu68k_map_set(m68k_read8_map, 0x600000, 0x7fffff, PicoRead8_plk3, 1); + cpu68k_map_set(m68k_write8_map, 0x600000, 0x6fffff, PicoWrite8_plk3p, 1); + cpu68k_map_set(m68k_write8_map, 0x700000, 0x7fffff, PicoWrite8_plk3b, 1); +} + +void carthw_prot_lk3_startup(void) +{ + int ret; + + elprintf(EL_STATUS, "lk3 prot emu startup"); + + // allocate space for bank0 backup + ret = PicoCartResize(Pico.romsize + 0x8000); + if (ret != 0) { + elprintf(EL_STATUS, "OOM"); + return; + } + memcpy(Pico.rom + Pico.romsize, Pico.rom, 0x8000); + + PicoCartMemSetup = carthw_prot_lk3_mem_setup; +} + diff --git a/waterbox/picodrive/pico/carthw/carthw.h b/waterbox/picodrive/pico/carthw/carthw.h new file mode 100644 index 0000000000..869a5cd64f --- /dev/null +++ b/waterbox/picodrive/pico/carthw/carthw.h @@ -0,0 +1,28 @@ + +/* svp */ +#include "svp/ssp16.h" + +typedef struct { + unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff) + unsigned char dram[0x20000]; + ssp1601_t ssp1601; +} svp_t; + +extern svp_t *svp; + +void PicoSVPInit(void); +void PicoSVPStartup(void); +void PicoSVPMemSetup(void); + +/* misc */ +void carthw_ssf2_startup(void); +void carthw_Xin1_startup(void); +void carthw_realtec_startup(void); +void carthw_radica_startup(void); +void carthw_pier_startup(void); + +void carthw_sprot_startup(void); +void carthw_sprot_new_location(unsigned int a, + unsigned int mask, unsigned short val, int is_ro); + +void carthw_prot_lk3_startup(void); diff --git a/waterbox/picodrive/pico/carthw/svp/imageformat.txt b/waterbox/picodrive/pico/carthw/svp/imageformat.txt new file mode 100644 index 0000000000..a16eae7a7d --- /dev/null +++ b/waterbox/picodrive/pico/carthw/svp/imageformat.txt @@ -0,0 +1,67 @@ + +vscroll: 1 (0); 209 (26) - alternates every 4 frames +vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f; high 3980-999f) +name table address: c000 +seen DMAs (in order): [300002-3026c3]->[0020-26e1] len 4961 + [3026c2-303943]->[26e0-3961] len 2369 + [303942-306003]->[72e0-99a1] len 4961 + --- + [306002-3086c3]->[3980-6041] len 4961 + [3086c2-309943]->[6040-72c1] len 2369 + [309942-30c003]->[72e0-99a2] len 4961 +tile arrangement: + +000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 +001: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 +002: 001 003 005 007 009 00b 00d 00f 011 013 015 017 019 01b 01d 01f 021 023 025 027 029 02b 02d 02f 031 033 035 037 039 03b 03d 03f +003: 002 004 006 008 00a 00c 00e 010 012 014 016 018 01a 01c 01e 020 022 024 026 028 02a 02c 02e 030 032 034 036 038 03a 03c 03e 040 +004: 041 043 045 047 049 04b 04d 04f 051 053 055 057 059 05b 05d 05f 061 063 065 067 069 06b 06d 06f 071 073 075 077 079 07b 07d 07f +005: 042 044 046 048 04a 04c 04e 050 052 054 056 058 05a 05c 05e 060 062 064 066 068 06a 06c 06e 070 072 074 076 078 07a 07c 07e 080 +006: 081 083 085 087 089 08b 08d 08f 091 093 095 097 099 09b 09d 09f 0a1 0a3 0a5 0a7 0a9 0ab 0ad 0af 0b1 0b3 0b5 0b7 0b9 0bb 0bd 0bf +007: 082 084 086 088 08a 08c 08e 090 092 094 096 098 09a 09c 09e 0a0 0a2 0a4 0a6 0a8 0aa 0ac 0ae 0b0 0b2 0b4 0b6 0b8 0ba 0bc 0be 0c0 +008: 0c1 0c3 0c5 0c7 0c9 0cb 0cd 0cf 0d1 0d3 0d5 0d7 0d9 0db 0dd 0df 0e1 0e3 0e5 0e7 0e9 0eb 0ed 0ef 0f1 0f3 0f5 0f7 0f9 0fb 0fd 0ff +009: 0c2 0c4 0c6 0c8 0ca 0cc 0ce 0d0 0d2 0d4 0d6 0d8 0da 0dc 0de 0e0 0e2 0e4 0e6 0e8 0ea 0ec 0ee 0f0 0f2 0f4 0f6 0f8 0fa 0fc 0fe 100 +010: 101 103 105 107 109 10b 10d 10f 111 113 115 117 119 11b 11d 11f 121 123 125 127 129 12b 12d 12f 131 133 135 137 139 13b 13d 13f +011: 102 104 106 108 10a 10c 10e 110 112 114 116 118 11a 11c 11e 120 122 124 126 128 12a 12c 12e 130 132 134 136 138 13a 13c 13e 140 +012: 141 143 145 147 149 14b 14d 14f 151 153 155 157 159 15b 15d 15f 161 163 165 167 169 16b 16d 16f 171 173 175 177 179 17b 17d 17f +013: 142 144 146 148 14a 14c 14e 150 152 154 156 158 15a 15c 15e 160 162 164 166 168 16a 16c 16e 170 172 174 176 178 17a 17c 17e 180 +014: 181 183 185 187 189 18b 18d 18f 191 193 195 197 199 19b 19d 19f 1a1 1a3 1a5 1a7 1a9 1ab 1ad 1af 1b1 1b3 1b5 1b7 1b9 1bb 1bd 1bf +015: 182 184 186 188 18a 18c 18e 190 192 194 196 198 19a 19c 19e 1a0 1a2 1a4 1a6 1a8 1aa 1ac 1ae 1b0 1b2 1b4 1b6 1b8 1ba 1bc 1be 1c0 +016: 1c1 1c3 1c5 1c7 1c9 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb +017: 1c2 1c4 1c6 1c8 1ca 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc +018: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b +019: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c +020: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b +021: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c +022: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b +023: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c +024: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb +025: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc +026: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 +027: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 +028: 1cc 1ce 1d0 1d2 1d4 1d6 1d8 1da 1dc 1de 1e0 1e2 1e4 1e6 1e8 1ea 1ec 1ee 1f0 1f2 1f4 1f6 1f8 1fa 1fc 1fe 200 202 204 206 208 20a +029: 1cd 1cf 1d1 1d3 1d5 1d7 1d9 1db 1dd 1df 1e1 1e3 1e5 1e7 1e9 1eb 1ed 1ef 1f1 1f3 1f5 1f7 1f9 1fb 1fd 1ff 201 203 205 207 209 20b +030: 20c 20e 210 212 214 216 218 21a 21c 21e 220 222 224 226 228 22a 22c 22e 230 232 234 236 238 23a 23c 23e 240 242 244 246 248 24a +031: 20d 20f 211 213 215 217 219 21b 21d 21f 221 223 225 227 229 22b 22d 22f 231 233 235 237 239 23b 23d 23f 241 243 245 247 249 24b +032: 24c 24e 250 252 254 256 258 25a 25c 25e 260 262 264 266 268 26a 26c 26e 270 272 274 276 278 27a 27c 27e 280 282 284 286 288 28a +033: 24d 24f 251 253 255 257 259 25b 25d 25f 261 263 265 267 269 26b 26d 26f 271 273 275 277 279 27b 27d 27f 281 283 285 287 289 28b +034: 28c 28e 290 292 294 296 298 29a 29c 29e 2a0 2a2 2a4 2a6 2a8 2aa 2ac 2ae 2b0 2b2 2b4 2b6 2b8 2ba 2bc 2be 2c0 2c2 2c4 2c6 2c8 2ca +035: 28d 28f 291 293 295 297 299 29b 29d 29f 2a1 2a3 2a5 2a7 2a9 2ab 2ad 2af 2b1 2b3 2b5 2b7 2b9 2bb 2bd 2bf 2c1 2c3 2c5 2c7 2c9 2cb +036: 2cc 2ce 2d0 2d2 2d4 2d6 2d8 2da 2dc 2de 2e0 2e2 2e4 2e6 2e8 2ea 2ec 2ee 2f0 2f2 2f4 2f6 2f8 2fa 2fc 2fe 300 302 304 306 308 30a +037: 2cd 2cf 2d1 2d3 2d5 2d7 2d9 2db 2dd 2df 2e1 2e3 2e5 2e7 2e9 2eb 2ed 2ef 2f1 2f3 2f5 2f7 2f9 2fb 2fd 2ff 301 303 305 307 309 30b +038: 30c 30e 310 312 314 316 318 31a 31c 31e 320 322 324 326 328 32a 32c 32e 330 332 334 336 338 33a 33c 33e 340 342 344 346 348 34a +039: 30d 30f 311 313 315 317 319 31b 31d 31f 321 323 325 327 329 32b 32d 32f 331 333 335 337 339 33b 33d 33f 341 343 345 347 349 34b +040: 34c 34e 350 352 354 356 358 35a 35c 35e 360 362 364 366 368 36a 36c 36e 370 372 374 376 378 37a 37c 37e 380 382 384 386 388 38a +041: 34d 34f 351 353 355 357 359 35b 35d 35f 361 363 365 367 369 36b 36d 36f 371 373 375 377 379 37b 37d 37f 381 383 385 387 389 38b +042: 38c 38e 390 392 394 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb +043: 38d 38f 391 393 395 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc +044: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b +045: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c +046: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b +047: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c +048: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b +049: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c +050: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb +051: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc +052: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 +053: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 diff --git a/waterbox/picodrive/pico/carthw/svp/memory.c b/waterbox/picodrive/pico/carthw/svp/memory.c new file mode 100644 index 0000000000..b37985e91c --- /dev/null +++ b/waterbox/picodrive/pico/carthw/svp/memory.c @@ -0,0 +1,163 @@ +/* + * The SVP chip emulator, mem I/O stuff + * + * Copyright (c) Gražvydas "notaz" Ignotas, 2008 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "../../pico_int.h" +#include "../../memory.h" + +// for wait loop det +static void PicoWrite16_dram(u32 a, u32 d) +{ + a &= ~0xfe0000; + + if (d != 0) { + if (a == 0xfe06) // 30fe06 + svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06; + else if (a == 0xfe08) + svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08; + } + + ((u16 *)svp->dram)[a / 2] = d; +} + +// "cell arrange" 1: 390000-39ffff +static u32 PicoRead16_svpca1(u32 a) +{ + // this is 68k code rewritten + u32 a1 = a >> 1; + a1 = (a1 & 0x7001) | ((a1 & 0x3e) << 6) | ((a1 & 0xfc0) >> 5); + return ((u16 *)svp->dram)[a1]; +} + +// "cell arrange" 2: 3a0000-3affff +static u32 PicoRead16_svpca2(u32 a) +{ + u32 a1 = a >> 1; + a1 = (a1 & 0x7801) | ((a1 & 0x1e) << 6) | ((a1 & 0x7e0) >> 4); + return ((u16 *)svp->dram)[a1]; +} + +// IO/control area (0xa10000 - 0xa1ffff) +static u32 PicoRead16_svpr(u32 a) +{ + u32 d = 0; + + // regs + if ((a & ~0x0f) == 0xa15000) { + switch (a & 0xf) { + case 0: + case 2: + d = svp->ssp1601.gr[SSP_XST].h; + break; + + case 4: + d = svp->ssp1601.gr[SSP_PM0].h; + svp->ssp1601.gr[SSP_PM0].h &= ~1; + break; + } + +#if EL_LOGMASK & EL_SVP + { + static int a15004_looping = 0; + if (a == 0xa15004 && (d & 1)) + a15004_looping = 0; + + if (!a15004_looping) + elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a, d, SekPc); + + if (a == 0xa15004 && !(d&1)) { + if (!a15004_looping) + elprintf(EL_SVP, "SVP det TIGHT loop: a15004"); + a15004_looping = 1; + } + else + a15004_looping = 0; + } +#endif + return d; + } + + //if (a == 0x30fe02 && d == 0) + // elprintf(EL_ANOMALY, "SVP lag?"); + + return PicoRead16_io(a); +} + +// used in VR test mode +static u32 PicoRead8_svpr(u32 a) +{ + u32 d; + + if ((a & ~0x0f) != 0xa15000) + return PicoRead8_io(a); + + d = PicoRead16_svpr(a & ~1); + if (!(a & 1)) + d >>= 8; + return d; +} + +static void PicoWrite16_svpr(u32 a, u32 d) +{ + elprintf(EL_SVP, "SVP w16: [%06x] %04x @%06x", a, d, SekPc); + + if ((a & ~0x0f) == 0xa15000) { + if (a == 0xa15000 || a == 0xa15002) { + // just guessing here + svp->ssp1601.gr[SSP_XST].h = d; + svp->ssp1601.gr[SSP_PM0].h |= 2; + svp->ssp1601.emu_status &= ~SSP_WAIT_PM0; + } + //else if (a == 0xa15006) svp->ssp1601.gr[SSP_PM0].h = d | (d << 1); + // 0xa15006 probably has 'halt' + return; + } + + PicoWrite16_io(a, d); +} + +void PicoSVPMemSetup(void) +{ + // 68k memmap: + // DRAM + cpu68k_map_set(m68k_read8_map, 0x300000, 0x31ffff, svp->dram, 0); + cpu68k_map_set(m68k_read16_map, 0x300000, 0x31ffff, svp->dram, 0); + cpu68k_map_set(m68k_write8_map, 0x300000, 0x31ffff, svp->dram, 0); + cpu68k_map_set(m68k_write16_map, 0x300000, 0x31ffff, svp->dram, 0); + cpu68k_map_set(m68k_write16_map, 0x300000, 0x30ffff, PicoWrite16_dram, 1); + + // DRAM (cell arrange) + cpu68k_map_set(m68k_read16_map, 0x390000, 0x39ffff, PicoRead16_svpca1, 1); + cpu68k_map_set(m68k_read16_map, 0x3a0000, 0x3affff, PicoRead16_svpca2, 1); + + // regs + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_svpr, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_svpr, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_io, 1); // PicoWrite8_svpr + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_svpr, 1); +} + diff --git a/waterbox/picodrive/pico/carthw/svp/ssp16.c b/waterbox/picodrive/pico/carthw/svp/ssp16.c new file mode 100644 index 0000000000..2fb400152c --- /dev/null +++ b/waterbox/picodrive/pico/carthw/svp/ssp16.c @@ -0,0 +1,1250 @@ +/* + * basic, incomplete SSP160x (SSP1601?) interpreter + * with SVP memory controller emu + * + * Copyright (c) Gražvydas "notaz" Ignotas, 2008 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#define USE_DEBUGGER +/* detect ops with unimplemented/invalid fields. + * Useful for homebrew or if a new VR revision pops up. */ +//#define DO_CHECKS + +/* + * Register info + * + * 0. "-" + * size: 16 + * desc: Constant register with all bits set (0xffff). + * + * 1. "X" + * size: 16 + * desc: Generic register. When set, updates P (P = X * Y * 2) + * + * 2. "Y" + * size: 16 + * desc: Generic register. When set, updates P (P = X * Y * 2) + * + * 3. "A" + * size: 32 + * desc: Accumulator. + * + * 4. "ST" + * size: 16 + * desc: Status register. From MAME: bits 0-9 are CONTROL, other FLAG + * fedc ba98 7654 3210 + * 210 - RPL (?) "Loop size". If non-zero, makes (rX+) and (rX-) respectively + * modulo-increment and modulo-decrement. The value shows which + * power of 2 to use, i.e. 4 means modulo by 16. + * (e: fir16_32.sc, IIR_4B.SC, DECIM.SC) + * 43 - RB (?) + * 5 - GP0_0 (ST5?) Changed before acessing PM0 (affects banking?). + * 6 - GP0_1 (ST6?) Cleared before acessing PM0 (affects banking?). Set after. + * datasheet says these (5,6) bits correspond to hardware pins. + * 7 - IE (?) Not directly used by SVP code (never set, but preserved)? + * 8 - OP (?) Not used by SVP code (only cleared)? (MAME: saturated value + * (probably means clamping? i.e. 0x7ffc + 9 -> 0x7fff)) + * 9 - MACS (?) Not used by SVP code (only cleared)? (e: "mac shift") + * a - GPI_0 Interrupt 0 enable/status? + * b - GPI_1 Interrupt 1 enable/status? + * c - L L flag. Carry? + * d - Z Zero flag. + * e - OV Overflow flag. + * f - N Negative flag. + * seen directly changing code sequences: + * ldi ST, 0 ld A, ST ld A, ST ld A, ST ldi st, 20h + * ldi ST, 60h ori A, 60h and A, E8h and A, E8h + * ld ST, A ld ST, A ori 3 + * ld ST, A + * + * 5. "STACK" + * size: 16 + * desc: hw stack of 6 levels (according to datasheet) + * + * 6. "PC" + * size: 16 + * desc: Program counter. + * + * 7. "P" + * size: 32 + * desc: multiply result register. P = X * Y * 2 + * probably affected by MACS bit in ST. + * + * 8. "PM0" (PM from PMAR name from Tasco's docs) + * size: 16? + * desc: Programmable Memory access register. + * On reset, or when one (both?) GP0 bits are clear, + * acts as status for XST, mapped at 015004 at 68k side: + * bit0: ssp has written something to XST (cleared when 015004 is read) + * bit1: 68k has written something through a1500{0|2} (cleared on PM0 read) + * + * 9. "PM1" + * size: 16? + * desc: Programmable Memory access register. + * This reg. is only used as PMAR. + * + * 10. "PM2" + * size: 16? + * desc: Programmable Memory access register. + * This reg. is only used as PMAR. + * + * 11. "XST" + * size: 16? + * desc: eXternal STate. Mapped to a15000 and a15002 at 68k side. + * Can be programmed as PMAR? (only seen in test mode code) + * Affects PM0 when written to? + * + * 12. "PM4" + * size: 16? + * desc: Programmable Memory access register. + * This reg. is only used as PMAR. The most used PMAR by VR. + * + * 13. (unused by VR) + * + * 14. "PMC" (PMC from PMAC name from Tasco's docs) + * size: 32? + * desc: Programmable Memory access Control. Set using 2 16bit writes, + * first address, then mode word. After setting PMAC, PMAR sould + * be blind accessed (ld -, PMx or ld PMx, -) to program it for + * reading and writing respectively. + * Reading the register also shifts it's state (from "waiting for + * address" to "waiting for mode" and back). Reads always return + * address related to last PMx register accressed. + * (note: addresses do not wrap). + * + * 15. "AL" + * size: 16 + * desc: Accumulator Low. 16 least significant bits of accumulator. + * (normally reading acc (ld X, A) you get 16 most significant bits). + * + * + * There are 8 8-bit pointer registers rX. r0-r3 (ri) point to RAM0, r4-r7 (rj) point to RAM1. + * They can be accessed directly, or 2 indirection levels can be used [ (rX), ((rX)) ], + * which work similar to * and ** operators in C, only they use different memory banks and + * ((rX)) also does post-increment. First indirection level (rX) accesses RAMx, second accesses + * program memory at address read from (rX), and increments value in (rX). + * + * r0,r1,r2,r4,r5,r6 can be modified [ex: ldi r0, 5]. + * 3 modifiers can be applied (optional): + * + : post-increment [ex: ld a, (r0+) ]. Can be made modulo-increment by setting RPL bits in ST. + * - : post-decrement. Can be made modulo-decrement by setting RPL bits in ST (not sure). + * +!: post-increment, unaffected by RPL (probably). + * These are only used on 1st indirection level, so things like [ld a, ((r0+))] and [ld X, r6-] + * ar probably invalid. + * + * r3 and r7 are special and can not be changed (at least Samsung samples and VR code never do). + * They are fixed to the start of their RAM banks. (They are probably changeable for ssp1605+, + * Samsung's old DSP page claims that). + * 1 of these 4 modifiers must be used (short form direct addressing?): + * |00: RAMx[0] [ex: (r3|00), 0] (based on sample code) + * |01: RAMx[1] + * |10: RAMx[2] ? maybe 10h? accortding to Div_c_dp.sc, 2 + * |11: RAMx[3] + * + * + * Instruction notes + * + * ld a, * doesn't affect flags! (e: A_LAW.SC, Div_c_dp.sc) + * + * mld (rj), (ri) [, b] + * operation: A = 0; P = (rj) * (ri) + * notes: based on IIR_4B.SC sample. flags? what is b??? + * + * mpya (rj), (ri) [, b] + * name: multiply and add? + * operation: A += P; P = (rj) * (ri) + * + * mpys (rj), (ri), b + * name: multiply and subtract? + * notes: not used by VR code. + * + * mod cond, op + * mod cond, shr does arithmetic shift + * + * 'ld -, AL' and probably 'ld AL, -' are for dummy assigns + * + * memory map: + * 000000 - 1fffff ROM, accessable by both + * 200000 - 2fffff unused? + * 300000 - 31ffff DRAM, both + * 320000 - 38ffff unused? + * 390000 - 3907ff IRAM. can only be accessed by ssp? + * 390000 - 39ffff similar mapping to "cell arrange" in Sega CD, 68k only? + * 3a0000 - 3affff similar mapping to "cell arrange" in Sega CD, a bit different + * + * 30fe02 - 0 if SVP busy, 1 if done (set by SVP, checked and cleared by 68k) + * 30fe06 - also sync related. + * 30fe08 - job number [1-12] for SVP. 0 means no job. Set by 68k, read-cleared by VR. + * + * Assumptions and limitations in this code + * only Z and N status flags are emulated (others unused by VR) + * so all condition checks except N and Z are ignored (not used by VR) + * modifiers for 'OP a, ri' and ((ri)) are ignored (not used by VR) + * loop repeat mode when (ri) is destination is ignored + * ops not used by VR are not implemented + */ + +#include "../../pico_int.h" + +#define u32 unsigned int + +// 0 +#define rX ssp->gr[SSP_X].h +#define rY ssp->gr[SSP_Y].h +#define rA ssp->gr[SSP_A].h +#define rST ssp->gr[SSP_ST].h // 4 +#define rSTACK ssp->gr[SSP_STACK].h +#define rPC ssp->gr[SSP_PC].h +#define rP ssp->gr[SSP_P] +#define rPM0 ssp->gr[SSP_PM0].h // 8 +#define rPM1 ssp->gr[SSP_PM1].h +#define rPM2 ssp->gr[SSP_PM2].h +#define rXST ssp->gr[SSP_XST].h +#define rPM4 ssp->gr[SSP_PM4].h // 12 +// 13 +#define rPMC ssp->gr[SSP_PMC] // will keep addr in .l, mode in .h +#define rAL ssp->gr[SSP_A].l + +#define rA32 ssp->gr[SSP_A].v +#define rIJ ssp->r + +#define IJind (((op>>6)&4)|(op&3)) + +#define GET_PC() (PC - (unsigned short *)svp->iram_rom) +#define GET_PPC_OFFS() ((unsigned char *)PC - svp->iram_rom - 2) +#define SET_PC(d) PC = (unsigned short *)svp->iram_rom + d + +#define REG_READ(r) (((r) <= 4) ? ssp->gr[r].h : read_handlers[r]()) +#define REG_WRITE(r,d) { \ + int r1 = r; \ + if (r1 >= 4) write_handlers[r1](d); \ + else if (r1 > 0) ssp->gr[r1].h = d; \ +} + +// flags +#define SSP_FLAG_L (1<<0xc) +#define SSP_FLAG_Z (1<<0xd) +#define SSP_FLAG_V (1<<0xe) +#define SSP_FLAG_N (1<<0xf) + +// update ZN according to 32bit ACC. +#define UPD_ACC_ZN \ + rST &= ~(SSP_FLAG_Z|SSP_FLAG_N); \ + if (!rA32) rST |= SSP_FLAG_Z; \ + else rST |= (rA32>>16)&SSP_FLAG_N; + +// it seems SVP code never checks for L and OV, so we leave them out. +// rST |= (t>>4)&SSP_FLAG_L; +#define UPD_LZVN \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!rA32) rST |= SSP_FLAG_Z; \ + else rST |= (rA32>>16)&SSP_FLAG_N; + +// standard cond processing. +// again, only Z and N is checked, as VR doesn't seem to use any other conds. +#define COND_CHECK \ + switch (op&0xf0) { \ + case 0x00: cond = 1; break; /* always true */ \ + case 0x50: cond = !((rST ^ (op<<5)) & SSP_FLAG_Z); break; /* Z matches f(?) bit */ \ + case 0x70: cond = !((rST ^ (op<<7)) & SSP_FLAG_N); break; /* N matches f(?) bit */ \ + default:elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unimplemented cond @ %04x", GET_PPC_OFFS()); break; \ + } + +// ops with accumulator. +// how is low word really affected by these? +// nearly sure 'ld A' doesn't affect flags +#define OP_LDA(x) \ + ssp->gr[SSP_A].h = x + +#define OP_LDA32(x) \ + rA32 = x + +#define OP_SUBA(x) { \ + rA32 -= (x) << 16; \ + UPD_LZVN \ +} + +#define OP_SUBA32(x) { \ + rA32 -= (x); \ + UPD_LZVN \ +} + +#define OP_CMPA(x) { \ + u32 t = rA32 - ((x) << 16); \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!t) rST |= SSP_FLAG_Z; \ + else rST |= (t>>16)&SSP_FLAG_N; \ +} + +#define OP_CMPA32(x) { \ + u32 t = rA32 - (x); \ + rST &= ~(SSP_FLAG_L|SSP_FLAG_Z|SSP_FLAG_V|SSP_FLAG_N); \ + if (!t) rST |= SSP_FLAG_Z; \ + else rST |= (t>>16)&SSP_FLAG_N; \ +} + +#define OP_ADDA(x) { \ + rA32 += (x) << 16; \ + UPD_LZVN \ +} + +#define OP_ADDA32(x) { \ + rA32 += (x); \ + UPD_LZVN \ +} + +#define OP_ANDA(x) \ + rA32 &= (x) << 16; \ + UPD_ACC_ZN + +#define OP_ANDA32(x) \ + rA32 &= (x); \ + UPD_ACC_ZN + +#define OP_ORA(x) \ + rA32 |= (x) << 16; \ + UPD_ACC_ZN + +#define OP_ORA32(x) \ + rA32 |= (x); \ + UPD_ACC_ZN + +#define OP_EORA(x) \ + rA32 ^= (x) << 16; \ + UPD_ACC_ZN + +#define OP_EORA32(x) \ + rA32 ^= (x); \ + UPD_ACC_ZN + + +#define OP_CHECK32(OP) { \ + if ((op & 0x0f) == SSP_P) { /* A <- P */ \ + read_P(); /* update P */ \ + OP(rP.v); \ + break; \ + } \ + if ((op & 0x0f) == SSP_A) { /* A <- A */ \ + OP(rA32); \ + break; \ + } \ +} + + +#ifdef DO_CHECKS +#define CHECK_IMM16() if (op&0x1ff) elprintf(EL_ANOMALY, "imm bits! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_B_SET() if (op&0x100) elprintf(EL_ANOMALY, "b set! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_B_CLEAR() if (!(op&0x100)) elprintf(EL_ANOMALY, "b clear! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_MOD() if (op&0x00c) elprintf(EL_ANOMALY, "mod bits! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_10f() if (op&0x10f) elprintf(EL_ANOMALY, "bits 10f! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_008() if (op&0x008) elprintf(EL_ANOMALY, "bits 008! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_00f() if (op&0x00f) elprintf(EL_ANOMALY, "bits 00f! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_0f0() if (op&0x0f0) elprintf(EL_ANOMALY, "bits 0f0! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_1f0() if (op&0x1f0) elprintf(EL_ANOMALY, "bits 1f0! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_RPL() if (rST&7) elprintf(EL_ANOMALY, "unhandled RPL! %04x @ %04x", op, GET_PPC_OFFS()) +#define CHECK_ST(d) if((rST^d)&0xf98)elprintf(EL_ANOMALY, "ssp FIXME ST %04x -> %04x @ %04x", rST, d, GET_PPC_OFFS()) +#else +#define CHECK_IMM16() +#define CHECK_B_SET() +#define CHECK_B_CLEAR() +#define CHECK_MOD() +#define CHECK_10f() +#define CHECK_008() +#define CHECK_00f() +#define CHECK_0f0() +#define CHECK_1f0() +#define CHECK_RPL() +#define CHECK_ST(d) +#endif + +ssp1601_t *ssp = NULL; +static unsigned short *PC; +static int g_cycles; + +#ifdef USE_DEBUGGER +static int running = 0; +static int last_iram = 0; +#endif + +// ----------------------------------------------------- +// register i/o handlers + +// 0-4, 13 +static u32 read_unknown(void) +{ + elprintf(EL_ANOMALY|EL_SVP, "ssp FIXME: unknown read @ %04x", GET_PPC_OFFS()); + return 0; +} + +static void write_unknown(u32 d) +{ + elprintf(EL_ANOMALY|EL_SVP, "ssp FIXME: unknown write @ %04x", GET_PPC_OFFS()); +} + +// 4 +static void write_ST(u32 d) +{ + CHECK_ST(d); + rST = d; +} + +// 5 +static u32 read_STACK(void) +{ + --rSTACK; + if ((short)rSTACK < 0) { + rSTACK = 5; + elprintf(EL_ANOMALY|EL_SVP, "ssp FIXME: stack underflow! (%i) @ %04x", rSTACK, GET_PPC_OFFS()); + } + return ssp->stack[rSTACK]; +} + +static void write_STACK(u32 d) +{ + if (rSTACK >= 6) { + elprintf(EL_ANOMALY|EL_SVP, "ssp FIXME: stack overflow! (%i) @ %04x", rSTACK, GET_PPC_OFFS()); + rSTACK = 0; + } + ssp->stack[rSTACK++] = d; +} + +// 6 +static u32 read_PC(void) +{ + return GET_PC(); +} + +static void write_PC(u32 d) +{ + SET_PC(d); + g_cycles--; +} + +// 7 +static u32 read_P(void) +{ + int m1 = (signed short)rX; + int m2 = (signed short)rY; + rP.v = (m1 * m2 * 2); + return rP.h; +} + +// ----------------------------------------------------- + +static int get_inc(int mode) +{ + int inc = (mode >> 11) & 7; + if (inc != 0) { + if (inc != 7) inc--; + inc = 1 << inc; // 0 1 2 4 8 16 32 128 + if (mode & 0x8000) inc = -inc; // decrement mode + } + return inc; +} + +#define overwrite_write(dst, d) \ +{ \ + if (d & 0xf000) { dst &= ~0xf000; dst |= d & 0xf000; } \ + if (d & 0x0f00) { dst &= ~0x0f00; dst |= d & 0x0f00; } \ + if (d & 0x00f0) { dst &= ~0x00f0; dst |= d & 0x00f0; } \ + if (d & 0x000f) { dst &= ~0x000f; dst |= d & 0x000f; } \ +} + +static u32 pm_io(int reg, int write, u32 d) +{ + unsigned int *pmac; + + if (ssp->emu_status & SSP_PMC_SET) + { + // this MUST be blind r or w + if ((*(PC-1) & 0xff0f) && (*(PC-1) & 0xfff0)) { + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: tried to set PM%i (%c) with non-blind i/o %08x @ %04x", + reg, write ? 'w' : 'r', rPMC.v, GET_PPC_OFFS()); + ssp->emu_status &= ~SSP_PMC_SET; + return 0; + } + elprintf(EL_SVP, "PM%i (%c) set to %08x @ %04x", reg, write ? 'w' : 'r', rPMC.v, GET_PPC_OFFS()); + pmac = write ? ssp->pmac_write : ssp->pmac_read; + pmac[reg] = rPMC.v; + ssp->emu_status &= ~SSP_PMC_SET; + if ((rPMC.v & 0x7fffff) == 0x1c8000 || (rPMC.v & 0x7fffff) == 0x1c8240) { + elprintf(EL_SVP, "ssp IRAM copy from %06x to %04x", (ssp->RAM1[0]-1)<<1, (rPMC.v&0x7fff)<<1); +#ifdef USE_DEBUGGER + last_iram = (ssp->RAM1[0]-1)<<1; +#endif + } + return 0; + } + + // just in case + if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: PM%i (%c) with only addr set @ %04x", + reg, write ? 'w' : 'r', GET_PPC_OFFS()); + ssp->emu_status &= ~SSP_PMC_HAVE_ADDR; + } + + if (reg == 4 || (rST & 0x60)) + { + #define CADDR ((((mode<<16)&0x7f0000)|addr)<<1) + unsigned short *dram = (unsigned short *)svp->dram; + if (write) + { + int mode = ssp->pmac_write[reg]>>16; + int addr = ssp->pmac_write[reg]&0xffff; + if ((mode & 0xb800) == 0xb800) + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: mode %04x", mode); + if ((mode & 0x43ff) == 0x0018) // DRAM + { + int inc = get_inc(mode); + elprintf(EL_SVP, "ssp PM%i DRAM w [%06x] %04x (inc %i, ovrw %i)", + reg, CADDR, d, inc, (mode>>10)&1); + if (mode & 0x0400) { + overwrite_write(dram[addr], d); + } else dram[addr] = d; + ssp->pmac_write[reg] += inc; + } + else if ((mode & 0xfbff) == 0x4018) // DRAM, cell inc + { + elprintf(EL_SVP, "ssp PM%i DRAM w [%06x] %04x (cell inc, ovrw %i) @ %04x", + reg, CADDR, d, (mode>>10)&1, GET_PPC_OFFS()); + if (mode & 0x0400) { + overwrite_write(dram[addr], d); + } else dram[addr] = d; + ssp->pmac_write[reg] += (addr&1) ? 31 : 1; + } + else if ((mode & 0x47ff) == 0x001c) // IRAM + { + int inc = get_inc(mode); + if ((addr&0xfc00) != 0x8000) + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: invalid IRAM addr: %04x", addr<<1); + elprintf(EL_SVP, "ssp IRAM w [%06x] %04x (inc %i)", (addr<<1)&0x7ff, d, inc); + ((unsigned short *)svp->iram_rom)[addr&0x3ff] = d; + ssp->pmac_write[reg] += inc; + } + else + { + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: PM%i unhandled write mode %04x, [%06x] %04x @ %04x", + reg, mode, CADDR, d, GET_PPC_OFFS()); + } + } + else + { + int mode = ssp->pmac_read[reg]>>16; + int addr = ssp->pmac_read[reg]&0xffff; + if ((mode & 0xfff0) == 0x0800) // ROM, inc 1, verified to be correct + { + elprintf(EL_SVP, "ssp ROM r [%06x] %04x", CADDR, + ((unsigned short *)Pico.rom)[addr|((mode&0xf)<<16)]); + ssp->pmac_read[reg] += 1; + d = ((unsigned short *)Pico.rom)[addr|((mode&0xf)<<16)]; + } + else if ((mode & 0x47ff) == 0x0018) // DRAM + { + int inc = get_inc(mode); + elprintf(EL_SVP, "ssp PM%i DRAM r [%06x] %04x (inc %i)", reg, CADDR, dram[addr]); + d = dram[addr]; + ssp->pmac_read[reg] += inc; + } + else + { + elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: PM%i unhandled read mode %04x, [%06x] @ %04x", + reg, mode, CADDR, GET_PPC_OFFS()); + d = 0; + } + } + + // PMC value corresponds to last PMR accessed (not sure). + pmac = write ? ssp->pmac_write : ssp->pmac_read; + rPMC.v = pmac[reg]; + + return d; + } + + return (u32)-1; +} + +// 8 +static u32 read_PM0(void) +{ + u32 d = pm_io(0, 0, 0); + if (d != (u32)-1) return d; + elprintf(EL_SVP, "PM0 raw r %04x @ %04x", rPM0, GET_PPC_OFFS()); + d = rPM0; + if (!(d & 2) && (GET_PPC_OFFS() == 0x800 || GET_PPC_OFFS() == 0x1851E)) { + ssp->emu_status |= SSP_WAIT_PM0; elprintf(EL_SVP, "det TIGHT loop: PM0"); + } + rPM0 &= ~2; // ? + return d; +} + +static void write_PM0(u32 d) +{ + u32 r = pm_io(0, 1, d); + if (r != (u32)-1) return; + elprintf(EL_SVP, "PM0 raw w %04x @ %04x", d, GET_PPC_OFFS()); + rPM0 = d; +} + +// 9 +static u32 read_PM1(void) +{ + u32 d = pm_io(1, 0, 0); + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM1 raw r %04x @ %04x", rPM1, GET_PPC_OFFS()); + return rPM1; +} + +static void write_PM1(u32 d) +{ + u32 r = pm_io(1, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM1 raw w %04x @ %04x", d, GET_PPC_OFFS()); + rPM1 = d; +} + +// 10 +static u32 read_PM2(void) +{ + u32 d = pm_io(2, 0, 0); + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM2 raw r %04x @ %04x", rPM2, GET_PPC_OFFS()); + return rPM2; +} + +static void write_PM2(u32 d) +{ + u32 r = pm_io(2, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM2 raw w %04x @ %04x", d, GET_PPC_OFFS()); + rPM2 = d; +} + +// 11 +static u32 read_XST(void) +{ + // can be removed? + u32 d = pm_io(3, 0, 0); + if (d != (u32)-1) return d; + + elprintf(EL_SVP, "XST raw r %04x @ %04x", rXST, GET_PPC_OFFS()); + return rXST; +} + +static void write_XST(u32 d) +{ + // can be removed? + u32 r = pm_io(3, 1, d); + if (r != (u32)-1) return; + + elprintf(EL_SVP, "XST raw w %04x @ %04x", d, GET_PPC_OFFS()); + rPM0 |= 1; + rXST = d; +} + +// 12 +static u32 read_PM4(void) +{ + u32 d = pm_io(4, 0, 0); + + if (d == 0) { + switch (GET_PPC_OFFS()) { + case 0x0854: ssp->emu_status |= SSP_WAIT_30FE08; elprintf(EL_SVP, "det TIGHT loop: [30fe08]"); break; + case 0x4f12: ssp->emu_status |= SSP_WAIT_30FE06; elprintf(EL_SVP, "det TIGHT loop: [30fe06]"); break; + } + } + + if (d != (u32)-1) return d; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM4 raw r %04x @ %04x", rPM4, GET_PPC_OFFS()); + return rPM4; +} + +static void write_PM4(u32 d) +{ + u32 r = pm_io(4, 1, d); + if (r != (u32)-1) return; + // can be removed? + elprintf(EL_SVP|EL_ANOMALY, "PM4 raw w %04x @ %04x", d, GET_PPC_OFFS()); + rPM4 = d; +} + +// 14 +static u32 read_PMC(void) +{ + elprintf(EL_SVP, "PMC r a %04x (st %c) @ %04x", rPMC.l, + (ssp->emu_status & SSP_PMC_HAVE_ADDR) ? 'm' : 'a', GET_PPC_OFFS()); + if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { + //if (ssp->emu_status & SSP_PMC_SET) + // elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); + ssp->emu_status |= SSP_PMC_SET; + ssp->emu_status &= ~SSP_PMC_HAVE_ADDR; + return ((rPMC.l << 4) & 0xfff0) | ((rPMC.l >> 4) & 0xf); + } else { + ssp->emu_status |= SSP_PMC_HAVE_ADDR; + return rPMC.l; + } +} + +static void write_PMC(u32 d) +{ + if (ssp->emu_status & SSP_PMC_HAVE_ADDR) { + //if (ssp->emu_status & SSP_PMC_SET) + // elprintf(EL_ANOMALY|EL_SVP, "prev PMC not used @ %04x", GET_PPC_OFFS()); + ssp->emu_status |= SSP_PMC_SET; + ssp->emu_status &= ~SSP_PMC_HAVE_ADDR; + rPMC.h = d; + elprintf(EL_SVP, "PMC w m %04x @ %04x", rPMC.h, GET_PPC_OFFS()); + } else { + ssp->emu_status |= SSP_PMC_HAVE_ADDR; + rPMC.l = d; + elprintf(EL_SVP, "PMC w a %04x @ %04x", rPMC.l, GET_PPC_OFFS()); + } +} + +// 15 +static u32 read_AL(void) +{ + if (*(PC-1) == 0x000f) + elprintf(EL_SVP, "ssp dummy PM assign %08x @ %04x", rPMC.v, GET_PPC_OFFS()); + ssp->emu_status &= ~(SSP_PMC_SET|SSP_PMC_HAVE_ADDR); // ? + return rAL; +} + +static void write_AL(u32 d) +{ + rAL = d; +} + + +typedef u32 (*read_func_t)(void); +typedef void (*write_func_t)(u32 d); + +static read_func_t read_handlers[16] = +{ + read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A + read_unknown, // 4 ST + read_STACK, + read_PC, + read_P, + read_PM0, // 8 + read_PM1, + read_PM2, + read_XST, + read_PM4, // 12 + read_unknown, // 13 gr13 + read_PMC, + read_AL +}; + +static write_func_t write_handlers[16] = +{ + write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A +// write_unknown, // 4 ST + write_ST, // 4 ST (debug hook) + write_STACK, + write_PC, + write_unknown, // 7 P + write_PM0, // 8 + write_PM1, + write_PM2, + write_XST, + write_PM4, // 12 + write_unknown, // 13 gr13 + write_PMC, + write_AL +}; + +// ----------------------------------------------------- +// pointer register handlers + +// +#define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18) + +static u32 ptr1_read_(int ri, int isj2, int modi3) +{ + //int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + u32 mask, add = 0, t = ri | isj2 | modi3; + unsigned char *rp = NULL; + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: return ssp->RAM0[ssp->r0[t&3]]; + case 0x03: return ssp->RAM0[0]; + case 0x04: + case 0x05: + case 0x06: return ssp->RAM1[ssp->r1[t&3]]; + case 0x07: return ssp->RAM1[0]; + // mod=1 (01), "+!" + case 0x08: + case 0x09: + case 0x0a: return ssp->RAM0[ssp->r0[t&3]++]; + case 0x0b: return ssp->RAM0[1]; + case 0x0c: + case 0x0d: + case 0x0e: return ssp->RAM1[ssp->r1[t&3]++]; + case 0x0f: return ssp->RAM1[1]; + // mod=2 (10), "-" + case 0x10: + case 0x11: + case 0x12: rp = &ssp->r0[t&3]; t = ssp->RAM0[*rp]; + if (!(rST&7)) { (*rp)--; return t; } + add = -1; goto modulo; + case 0x13: return ssp->RAM0[2]; + case 0x14: + case 0x15: + case 0x16: rp = &ssp->r1[t&3]; t = ssp->RAM1[*rp]; + if (!(rST&7)) { (*rp)--; return t; } + add = -1; goto modulo; + case 0x17: return ssp->RAM1[2]; + // mod=3 (11), "+" + case 0x18: + case 0x19: + case 0x1a: rp = &ssp->r0[t&3]; t = ssp->RAM0[*rp]; + if (!(rST&7)) { (*rp)++; return t; } + add = 1; goto modulo; + case 0x1b: return ssp->RAM0[3]; + case 0x1c: + case 0x1d: + case 0x1e: rp = &ssp->r1[t&3]; t = ssp->RAM1[*rp]; + if (!(rST&7)) { (*rp)++; return t; } + add = 1; goto modulo; + case 0x1f: return ssp->RAM1[3]; + } + + return 0; + +modulo: + mask = (1 << (rST&7)) - 1; + *rp = (*rp & ~mask) | ((*rp + add) & mask); + return t; +} + +static void ptr1_write(int op, u32 d) +{ + int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: ssp->RAM0[ssp->r0[t&3]] = d; return; + case 0x03: ssp->RAM0[0] = d; return; + case 0x04: + case 0x05: + case 0x06: ssp->RAM1[ssp->r1[t&3]] = d; return; + case 0x07: ssp->RAM1[0] = d; return; + // mod=1 (01), "+!" + // mod=3, "+" + case 0x08: + case 0x09: + case 0x0a: ssp->RAM0[ssp->r0[t&3]++] = d; return; + case 0x0b: ssp->RAM0[1] = d; return; + case 0x0c: + case 0x0d: + case 0x0e: ssp->RAM1[ssp->r1[t&3]++] = d; return; + case 0x0f: ssp->RAM1[1] = d; return; + // mod=2 (10), "-" + case 0x10: + case 0x11: + case 0x12: ssp->RAM0[ssp->r0[t&3]--] = d; CHECK_RPL(); return; + case 0x13: ssp->RAM0[2] = d; return; + case 0x14: + case 0x15: + case 0x16: ssp->RAM1[ssp->r1[t&3]--] = d; CHECK_RPL(); return; + case 0x17: ssp->RAM1[2] = d; return; + // mod=3 (11), "+" + case 0x18: + case 0x19: + case 0x1a: ssp->RAM0[ssp->r0[t&3]++] = d; CHECK_RPL(); return; + case 0x1b: ssp->RAM0[3] = d; return; + case 0x1c: + case 0x1d: + case 0x1e: ssp->RAM1[ssp->r1[t&3]++] = d; CHECK_RPL(); return; + case 0x1f: ssp->RAM1[3] = d; return; + } +} + +static u32 ptr2_read(int op) +{ + int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); + switch (t) + { + // mod=0 (00) + case 0x00: + case 0x01: + case 0x02: mv = ssp->RAM0[ssp->r0[t&3]]++; break; + case 0x03: mv = ssp->RAM0[0]++; break; + case 0x04: + case 0x05: + case 0x06: mv = ssp->RAM1[ssp->r1[t&3]]++; break; + case 0x07: mv = ssp->RAM1[0]++; break; + // mod=1 (01) + case 0x0b: mv = ssp->RAM0[1]++; break; + case 0x0f: mv = ssp->RAM1[1]++; break; + // mod=2 (10) + case 0x13: mv = ssp->RAM0[2]++; break; + case 0x17: mv = ssp->RAM1[2]++; break; + // mod=3 (11) + case 0x1b: mv = ssp->RAM0[3]++; break; + case 0x1f: mv = ssp->RAM1[3]++; break; + default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: invalid mod in ((rX))? @ %04x", GET_PPC_OFFS()); + return 0; + } + + return ((unsigned short *)svp->iram_rom)[mv]; +} + + +// ----------------------------------------------------- + +#if defined(USE_DEBUGGER) +static void debug_dump2file(const char *fname, void *mem, int len) +{ + FILE *f = fopen(fname, "wb"); + unsigned short *p = mem; + int i; + if (f) { + for (i = 0; i < len/2; i++) p[i] = (p[i]<<8) | (p[i]>>8); + fwrite(mem, 1, len, f); + fclose(f); + for (i = 0; i < len/2; i++) p[i] = (p[i]<<8) | (p[i]>>8); + printf("dumped to %s\n", fname); + } + else + printf("dump failed\n"); +} +#endif + +#ifdef USE_DEBUGGER +static void debug_dump(void) +{ + printf("GR0: %04x X: %04x Y: %04x A: %08x\n", ssp->gr[SSP_GR0].h, rX, rY, ssp->gr[SSP_A].v); + printf("PC: %04x (%04x) P: %08x\n", GET_PC(), GET_PC() << 1, rP.v); + printf("PM0: %04x PM1: %04x PM2: %04x\n", rPM0, rPM1, rPM2); + printf("XST: %04x PM4: %04x PMC: %08x\n", rXST, rPM4, rPMC.v); + printf(" ST: %04x %c%c%c%c, GP0_0 %i, GP0_1 %i\n", rST, rST&SSP_FLAG_N?'N':'n', rST&SSP_FLAG_V?'V':'v', + rST&SSP_FLAG_Z?'Z':'z', rST&SSP_FLAG_L?'L':'l', (rST>>5)&1, (rST>>6)&1); + printf("STACK: %i %04x %04x %04x %04x %04x %04x\n", rSTACK, ssp->stack[0], ssp->stack[1], + ssp->stack[2], ssp->stack[3], ssp->stack[4], ssp->stack[5]); + printf("r0-r2: %02x %02x %02x r4-r6: %02x %02x %02x\n", rIJ[0], rIJ[1], rIJ[2], rIJ[4], rIJ[5], rIJ[6]); + elprintf(EL_SVP, "cycles: %i, emu_status: %x", g_cycles, ssp->emu_status); +} + +static void debug_dump_mem(void) +{ + int h, i; + printf("RAM0\n"); + for (h = 0; h < 32; h++) + { + if (h == 16) printf("RAM1\n"); + printf("%03x:", h*16); + for (i = 0; i < 16; i++) + printf(" %04x", ssp->RAM[h*16+i]); + printf("\n"); + } +} + +static int bpts[10] = { 0, }; + +static void debug(unsigned int pc, unsigned int op) +{ + static char buffo[64] = {0,}; + char buff[64] = {0,}; + int i; + + if (running) { + for (i = 0; i < 10; i++) + if (pc != 0 && bpts[i] == pc) { + printf("breakpoint %i\n", i); + running = 0; + break; + } + } + if (running) return; + + printf("%04x (%02x) @ %04x\n", op, op >> 9, pc<<1); + + while (1) + { + printf("dbg> "); + fflush(stdout); + fgets(buff, sizeof(buff), stdin); + if (buff[0] == '\n') strcpy(buff, buffo); + else strcpy(buffo, buff); + + switch (buff[0]) { + case 0: exit(0); + case 'c': + case 'r': running = 1; return; + case 's': + case 'n': return; + case 'x': debug_dump(); break; + case 'm': debug_dump_mem(); break; + case 'b': { + char *baddr = buff + 2; + i = 0; + if (buff[3] == ' ') { i = buff[2] - '0'; baddr = buff + 4; } + bpts[i] = strtol(baddr, NULL, 16) >> 1; + printf("breakpoint %i set @ %04x\n", i, bpts[i]<<1); + break; + } + case 'd': + sprintf(buff, "iramrom_%04x.bin", last_iram); + debug_dump2file(buff, svp->iram_rom, sizeof(svp->iram_rom)); + debug_dump2file("dram.bin", svp->dram, sizeof(svp->dram)); + break; + default: printf("unknown command\n"); break; + } + } +} +#endif // USE_DEBUGGER + + +void ssp1601_reset(ssp1601_t *l_ssp) +{ + ssp = l_ssp; + ssp->emu_status = 0; + ssp->gr[SSP_GR0].v = 0xffff0000; + rPC = 0x400; + rSTACK = 0; // ? using ascending stack + rST = 0; +} + + +void ssp1601_run(int cycles) +{ + SET_PC(rPC); + + g_cycles = cycles; + + while (g_cycles > 0 && !(ssp->emu_status & SSP_WAIT_MASK)) + { + int op; + u32 tmpv; + + op = *PC++; +#ifdef USE_DEBUGGER + debug(GET_PC()-1, op); +#endif + switch (op >> 9) + { + // ld d, s + case 0x00: + CHECK_B_SET(); + if (op == 0) break; // nop + if (op == ((SSP_A<<4)|SSP_P)) { // A <- P + read_P(); // update P + rA32 = rP.v; + } + else + { + tmpv = REG_READ(op & 0x0f); + REG_WRITE((op & 0xf0) >> 4, tmpv); + } + break; + + // ld d, (ri) + case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break; + + // ld (ri), s + case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break; + + // ldi d, imm + case 0x04: CHECK_10f(); tmpv = *PC++; REG_WRITE((op & 0xf0) >> 4, tmpv); g_cycles--; break; + + // ld d, ((ri)) + case 0x05: CHECK_MOD(); tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); g_cycles -= 2; break; + + // ldi (ri), imm + case 0x06: tmpv = *PC++; ptr1_write(op, tmpv); g_cycles--; break; + + // ld adr, a + case 0x07: ssp->RAM[op & 0x1ff] = rA; break; + + // ld d, ri + case 0x09: CHECK_MOD(); tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break; + + // ld ri, s + case 0x0a: CHECK_MOD(); rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break; + + // ldi ri, simm + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: rIJ[(op>>8)&7] = op; break; + + // call cond, addr + case 0x24: { + int cond = 0; + CHECK_00f(); + COND_CHECK + if (cond) { int new_PC = *PC++; write_STACK(GET_PC()); SET_PC(new_PC); } + else PC++; + g_cycles--; // always 2 cycles + break; + } + + // ld d, (a) + case 0x25: + CHECK_10f(); + tmpv = ((unsigned short *)svp->iram_rom)[rA]; + REG_WRITE((op & 0xf0) >> 4, tmpv); + g_cycles -= 2; // 3 cycles total + break; + + // bra cond, addr + case 0x26: { + int cond = 0; + CHECK_00f(); + COND_CHECK + if (cond) { int new_PC = *PC++; SET_PC(new_PC); } + else PC++; + g_cycles--; + break; + } + + // mod cond, op + case 0x48: { + int cond = 0; + CHECK_008(); + COND_CHECK + if (cond) { + switch (op & 7) { + case 2: rA32 = (signed int)rA32 >> 1; break; // shr (arithmetic) + case 3: rA32 <<= 1; break; // shl + case 6: rA32 = -(signed int)rA32; break; // neg + case 7: if ((int)rA32 < 0) rA32 = -(signed int)rA32; break; // abs + default: elprintf(EL_SVP|EL_ANOMALY, "ssp FIXME: unhandled mod %i @ %04x", + op&7, GET_PPC_OFFS()); + } + UPD_ACC_ZN + } + break; + } + + // mpys? + case 0x1b: + CHECK_B_CLEAR(); + read_P(); // update P + rA32 -= rP.v; + UPD_ACC_ZN + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // mpya (rj), (ri), b + case 0x4b: + CHECK_B_CLEAR(); + read_P(); // update P + rA32 += rP.v; + UPD_ACC_ZN + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // mld (rj), (ri), b + case 0x5b: + CHECK_B_CLEAR(); + rA32 = 0; + rST &= 0x0fff; + rST |= SSP_FLAG_Z; + rX = ptr1_read_(op&3, 0, (op<<1)&0x18); + rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); + break; + + // OP a, s + case 0x10: CHECK_1f0(); OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break; + case 0x30: CHECK_1f0(); OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break; + case 0x40: CHECK_1f0(); OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break; + case 0x50: CHECK_1f0(); OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv); break; + case 0x60: CHECK_1f0(); OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break; + case 0x70: CHECK_1f0(); OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break; + + // OP a, (ri) + case 0x11: CHECK_0f0(); tmpv = ptr1_read(op); OP_SUBA(tmpv); break; + case 0x31: CHECK_0f0(); tmpv = ptr1_read(op); OP_CMPA(tmpv); break; + case 0x41: CHECK_0f0(); tmpv = ptr1_read(op); OP_ADDA(tmpv); break; + case 0x51: CHECK_0f0(); tmpv = ptr1_read(op); OP_ANDA(tmpv); break; + case 0x61: CHECK_0f0(); tmpv = ptr1_read(op); OP_ORA (tmpv); break; + case 0x71: CHECK_0f0(); tmpv = ptr1_read(op); OP_EORA(tmpv); break; + + // OP a, adr + case 0x03: tmpv = ssp->RAM[op & 0x1ff]; OP_LDA (tmpv); break; + case 0x13: tmpv = ssp->RAM[op & 0x1ff]; OP_SUBA(tmpv); break; + case 0x33: tmpv = ssp->RAM[op & 0x1ff]; OP_CMPA(tmpv); break; + case 0x43: tmpv = ssp->RAM[op & 0x1ff]; OP_ADDA(tmpv); break; + case 0x53: tmpv = ssp->RAM[op & 0x1ff]; OP_ANDA(tmpv); break; + case 0x63: tmpv = ssp->RAM[op & 0x1ff]; OP_ORA (tmpv); break; + case 0x73: tmpv = ssp->RAM[op & 0x1ff]; OP_EORA(tmpv); break; + + // OP a, imm + case 0x14: CHECK_IMM16(); tmpv = *PC++; OP_SUBA(tmpv); g_cycles--; break; + case 0x34: CHECK_IMM16(); tmpv = *PC++; OP_CMPA(tmpv); g_cycles--; break; + case 0x44: CHECK_IMM16(); tmpv = *PC++; OP_ADDA(tmpv); g_cycles--; break; + case 0x54: CHECK_IMM16(); tmpv = *PC++; OP_ANDA(tmpv); g_cycles--; break; + case 0x64: CHECK_IMM16(); tmpv = *PC++; OP_ORA (tmpv); g_cycles--; break; + case 0x74: CHECK_IMM16(); tmpv = *PC++; OP_EORA(tmpv); g_cycles--; break; + + // OP a, ((ri)) + case 0x15: CHECK_MOD(); tmpv = ptr2_read(op); OP_SUBA(tmpv); g_cycles -= 2; break; + case 0x35: CHECK_MOD(); tmpv = ptr2_read(op); OP_CMPA(tmpv); g_cycles -= 2; break; + case 0x45: CHECK_MOD(); tmpv = ptr2_read(op); OP_ADDA(tmpv); g_cycles -= 2; break; + case 0x55: CHECK_MOD(); tmpv = ptr2_read(op); OP_ANDA(tmpv); g_cycles -= 2; break; + case 0x65: CHECK_MOD(); tmpv = ptr2_read(op); OP_ORA (tmpv); g_cycles -= 2; break; + case 0x75: CHECK_MOD(); tmpv = ptr2_read(op); OP_EORA(tmpv); g_cycles -= 2; break; + + // OP a, ri + case 0x19: CHECK_MOD(); tmpv = rIJ[IJind]; OP_SUBA(tmpv); break; + case 0x39: CHECK_MOD(); tmpv = rIJ[IJind]; OP_CMPA(tmpv); break; + case 0x49: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ADDA(tmpv); break; + case 0x59: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ANDA(tmpv); break; + case 0x69: CHECK_MOD(); tmpv = rIJ[IJind]; OP_ORA (tmpv); break; + case 0x79: CHECK_MOD(); tmpv = rIJ[IJind]; OP_EORA(tmpv); break; + + // OP simm + case 0x1c: CHECK_B_SET(); OP_SUBA(op & 0xff); break; + case 0x3c: CHECK_B_SET(); OP_CMPA(op & 0xff); break; + case 0x4c: CHECK_B_SET(); OP_ADDA(op & 0xff); break; + case 0x5c: CHECK_B_SET(); OP_ANDA(op & 0xff); break; + case 0x6c: CHECK_B_SET(); OP_ORA (op & 0xff); break; + case 0x7c: CHECK_B_SET(); OP_EORA(op & 0xff); break; + + default: + elprintf(EL_ANOMALY|EL_SVP, "ssp FIXME unhandled op %04x @ %04x", op, GET_PPC_OFFS()); + break; + } + g_cycles--; + } + + rPC = GET_PC(); + read_P(); // update P +} + diff --git a/waterbox/picodrive/pico/carthw/svp/ssp16.h b/waterbox/picodrive/pico/carthw/svp/ssp16.h new file mode 100644 index 0000000000..318a4a7ecd --- /dev/null +++ b/waterbox/picodrive/pico/carthw/svp/ssp16.h @@ -0,0 +1,92 @@ +/* + * basic, incomplete SSP160x (SSP1601?) interpreter + * + * Copyright (c) Gražvydas "notaz" Ignotas, 2008 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// register names +enum { + SSP_GR0, SSP_X, SSP_Y, SSP_A, + SSP_ST, SSP_STACK, SSP_PC, SSP_P, + SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST, + SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL +}; + +typedef union +{ + unsigned int v; + struct { + unsigned short l; + unsigned short h; + }; +} ssp_reg_t; + +typedef struct +{ + union { + unsigned short RAM[256*2]; // 000 2 internal RAM banks + struct { + unsigned short RAM0[256]; + unsigned short RAM1[256]; + }; + }; + ssp_reg_t gr[16]; // 400 general registers + union { + unsigned char r[8]; // 440 BANK pointers + struct { + unsigned char r0[4]; + unsigned char r1[4]; + }; + }; + unsigned short stack[6]; // 448 + unsigned int pmac_read[6]; // 454 read modes/addrs for PM0-PM5 + unsigned int pmac_write[6]; // 46c write ... + // + #define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode + #define SSP_PMC_SET 0x0002 // PMAC is set + #define SSP_WAIT_PM0 0x2000 // bit1 in PM0 + #define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE06 to become non-zero + #define SSP_WAIT_30FE08 0x8000 // same for 30FE06 + #define SSP_WAIT_MASK 0xe000 + unsigned int emu_status; // 484 + /* used by recompiler only: */ + struct { + unsigned int ptr_rom; // 488 + unsigned int ptr_iram_rom; // 48c + unsigned int ptr_dram; // 490 + unsigned int iram_dirty; // 494 + unsigned int iram_context; // 498 + unsigned int ptr_btable; // 49c + unsigned int ptr_btable_iram; // 4a0 + unsigned int tmp0; // 4a4 + unsigned int tmp1; // 4a8 + unsigned int tmp2; // 4ac + } drc; +} ssp1601_t; + + +void ssp1601_reset(ssp1601_t *ssp); +void ssp1601_run(int cycles); + diff --git a/waterbox/picodrive/pico/carthw/svp/svp.c b/waterbox/picodrive/pico/carthw/svp/svp.c new file mode 100644 index 0000000000..811a515d8d --- /dev/null +++ b/waterbox/picodrive/pico/carthw/svp/svp.c @@ -0,0 +1,150 @@ +/* + * The SVP chip emulator + * + * Copyright (c) Gražvydas "notaz" Ignotas, 2008 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the organization nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +svp_t *svp = NULL; +int PicoSVPCycles = 850; // cycles/line, just a guess +static int svp_dyn_ready = 0; + +static void PicoSVPReset(void) +{ + elprintf(EL_SVP, "SVP reset"); + + memcpy(svp->iram_rom + 0x800, Pico.rom + 0x800, 0x20000 - 0x800); + ssp1601_reset(&svp->ssp1601); +#ifdef _SVP_DRC + if ((PicoOpt & POPT_EN_DRC) && svp_dyn_ready) + ssp1601_dyn_reset(&svp->ssp1601); +#endif +} + + +static void PicoSVPLine(void) +{ + int count = 1; +#if defined(__arm__) || defined(PSP) + // performance hack + static int delay_lines = 0; + delay_lines++; + if ((Pico.m.scanline&0xf) != 0xf && Pico.m.scanline != 261 && Pico.m.scanline != 311) + return; + count = delay_lines; + delay_lines = 0; +#endif + +#ifdef _SVP_DRC + if ((PicoOpt & POPT_EN_DRC) && svp_dyn_ready) + ssp1601_dyn_run(PicoSVPCycles * count); + else +#endif + { + ssp1601_run(PicoSVPCycles * count); + svp_dyn_ready = 0; // just in case + } + + // test mode + //if (Pico.m.frame_count == 13) PicoPad[0] |= 0xff; +} + + +static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp) +{ + if (source < Pico.romsize) // Rom + { + source -= 2; + *srcp = (unsigned short *)(Pico.rom + (source&~1)); + *limitp = (unsigned short *)(Pico.rom + Pico.romsize); + return 1; + } + else if ((source & 0xfe0000) == 0x300000) + { + elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x, len=%i", source, len); + source &= 0x1fffe; + source -= 2; + *srcp = (unsigned short *)(svp->dram + source); + *limitp = (unsigned short *)(svp->dram + sizeof(svp->dram)); + return 1; + } + else + elprintf(EL_VDPDMA|EL_SVP|EL_ANOMALY, "SVP FIXME unhandled DmaSlow from %06x, len=%i", source, len); + + return 0; +} + + +void PicoSVPInit(void) +{ +#ifdef _SVP_DRC + // this is to unmap tcache and make + // mem available for large ROMs, MCD, etc. + drc_cmn_cleanup(); +#endif +} + +static void PicoSVPExit(void) +{ +#ifdef _SVP_DRC + ssp1601_dyn_exit(); +#endif +} + + +void PicoSVPStartup(void) +{ + int ret; + + elprintf(EL_STATUS, "SVP startup"); + + ret = PicoCartResize(Pico.romsize + sizeof(*svp)); + if (ret != 0) { + elprintf(EL_STATUS|EL_SVP, "OOM for SVP data"); + return; + } + + svp = (void *) ((char *)Pico.rom + Pico.romsize); + memset(svp, 0, sizeof(*svp)); + + // init SVP compiler + svp_dyn_ready = 0; +#ifdef _SVP_DRC + if (PicoOpt & POPT_EN_DRC) { + if (ssp1601_dyn_startup()) + return; + svp_dyn_ready = 1; + } +#endif + + // init ok, setup hooks.. + PicoCartMemSetup = PicoSVPMemSetup; + PicoDmaHook = PicoSVPDma; + PicoResetHook = PicoSVPReset; + PicoLineHook = PicoSVPLine; + PicoAHW |= PAHW_SVP; +} + diff --git a/waterbox/picodrive/pico/carthw_cfg.c b/waterbox/picodrive/pico/carthw_cfg.c new file mode 100644 index 0000000000..91ddec74e6 --- /dev/null +++ b/waterbox/picodrive/pico/carthw_cfg.c @@ -0,0 +1,229 @@ +/* generated by ./tools/make_carthw_c, do not modify */ +static const char builtin_carthw_cfg[] = + "[]\n" + "check_str=0x150,\"Virtua Racing\"\n" + "check_str=0x810,\"OHMP\"\n" + "hw=svp\n" + "[]\n" + "check_str=0x150,\"VIRTUA RACING\"\n" + "check_str=0x810,\"OHMP\"\n" + "hw=svp\n" + "[]\n" + "check_str=0x100,\"SEGA PICO\"\n" + "hw=pico\n" + "[]\n" + "check_str=0x100,\"IMA IKUNOUJYUKU\"\n" + "hw=pico\n" + "[]\n" + "check_str=0x120,\"PUGGSY\"\n" + "prop=no_sram\n" + "[]\n" + "check_str=0x150,\"DINO DINI'S SOCCER\"\n" + "prop=filled_sram\n" + "[]\n" + "check_str=0x150,\"MICRO MACHINES II\"\n" + "prop=filled_sram\n" + "[]\n" + "check_str=0x150,\"32X SAMPLE PROGRAM\"\n" + "check_str=0x32b74c,\"Bishop Level\"\n" + "prop=force_6btn\n" + "[]\n" + "check_str=0x150,\"SUPER STREET FIGHTER2 The New Challengers\"\n" + "hw=ssf2_mapper\n" + "prop=no_sram\n" + "[]\n" + "check_str=0x150,\"PIER\"\n" + "check_str=0x610,\"Respect\"\n" + "hw=piersolar_mapper\n" + "[]\n" + "check_str=0x120,\"FLICKY\"\n" + "check_size_gt=0x020000\n" + "hw=x_in_1_mapper\n" + "[]\n" + "check_str=0x150,\"ROBOCOP 3\"\n" + "check_size_gt=0x080000\n" + "hw=x_in_1_mapper\n" + "[]\n" + "check_str=0x150,\"ALIEN 3\"\n" + "check_size_gt=0x080000\n" + "hw=x_in_1_mapper\n" + "[]\n" + "check_str=0x150,\" SHOVE IT!\"\n" + "check_size_gt=0x020000\n" + "hw=x_in_1_mapper\n" + "[]\n" + "check_str=0x150,\"MS PACMAN\"\n" + "check_size_gt=0x020000\n" + "hw=x_in_1_mapper\n" + "[]\n" + "check_str=0x150,\"KID CHAMELEON\"\n" + "check_size_gt=0x100000\n" + "hw=radica_mapper\n" + "[]\n" + "check_str=0x94,\"THE EARTH DEFEND\"\n" + "hw=realtec_mapper\n" + "[]\n" + "check_str=0xfe,\"WISEGAME 11-03-1993\"\n" + "hw=realtec_mapper\n" + "[]\n" + "check_str=0x95,\"MALLET LEGEND\"\n" + "hw=realtec_mapper\n" + "[]\n" + "check_str=0x150,\"COLLEGE SLAM\"\n" + "eeprom_type=3\n" + "eeprom_lines=8,0,0\n" + "[]\n" + "check_str=0x150,\"FRANK THOMAS BIGHURT BASEBAL\"\n" + "eeprom_type=3\n" + "eeprom_lines=8,0,0\n" + "[]\n" + "check_str=0x150,\"MICRO MACHINES II\"\n" + "sram_range=0x300000,0x380001\n" + "eeprom_type=2\n" + "eeprom_lines=9,8,7\n" + "[]\n" + "check_str=0x150,\" \"\n" + "check_csum=0x165e\n" + "sram_range=0x300000,0x380001\n" + "eeprom_type=2\n" + "eeprom_lines=9,8,7\n" + "[]\n" + "check_str=0x150,\" \"\n" + "check_csum=0x2c41\n" + "sram_range=0x300000,0x380001\n" + "eeprom_type=2\n" + "eeprom_lines=9,8,7\n" + "[]\n" + "check_str=0x150,\" \"\n" + "check_csum=0x168b\n" + "sram_range=0x300000,0x380001\n" + "eeprom_type=2\n" + "eeprom_lines=9,8,7\n" + "[]\n" + "check_str=0x150,\" \"\n" + "check_csum=0xcee0\n" + "sram_range=0x300000,0x380001\n" + "eeprom_type=2\n" + "eeprom_lines=9,8,7\n" + "[]\n" + "check_str=0x150,\"NBA JAM \"\n" + "eeprom_type=2\n" + "eeprom_lines=1,0,1\n" + "[]\n" + "check_str=0x150,\"NBA JAM TOURNAMENT EDITION\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=2\n" + "eeprom_lines=8,0,0\n" + "[]\n" + "check_str=0x150,\"NFL QUARTERBACK CLUB\"\n" + "eeprom_type=2\n" + "eeprom_lines=8,0,0\n" + "[]\n" + "check_str=0x150,\"NHLPA Hockey '93\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=1\n" + "eeprom_lines=6,7,7\n" + "[]\n" + "check_str=0x150,\"NHLPA HOCKEY '93\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=1\n" + "eeprom_lines=6,7,7\n" + "[]\n" + "check_str=0x150,\"RINGS OF POWER\"\n" + "sram_range=0x200000,0x200001\n" + "eeprom_type=1\n" + "eeprom_lines=6,7,7\n" + "[]\n" + "check_str=0x104,\" \"\n" + "check_crc32=0x10458e09\n" + "hw=prot\n" + "prot_ro_value16=0xa13000,0xffff00,0x28\n" + "[]\n" + "check_str=0x172,\"GAME : ELF WOR\"\n" + "hw=prot\n" + "prot_ro_value16=0x400000,-2,0x5500\n" + "prot_ro_value16=0x400002,-2,0xc900#checkisdoneiftheaboveonefails\n" + "prot_ro_value16=0x400004,-2,0x0f00\n" + "prot_ro_value16=0x400006,-2,0x1800#similartoabove\n" + "[]\n" + "check_str=0x104,\" \"\n" + "check_crc32=0xcbc38eea\n" + "hw=prot\n" + "prot_ro_value16=0x480000,0xff0000,0xaa00\n" + "prot_ro_value16=0x4a0000,0xff0000,0x0a00\n" + "prot_ro_value16=0x4c0000,0xff0000,0xf000\n" + "prot_ro_value16=0x400000,0xc00000,0x0000#defaultfor400000-7f0000\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0xc004219d\n" + "hw=prot_lk3\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0xaff46765\n" + "hw=prot\n" + "prot_rw_value16=0x400000,0xc00004,0\n" + "prot_rw_value16=0x400004,0xc00004,0\n" + "[]\n" + "check_str=0x118,\"CREATON. \"\n" + "check_crc32=0xddd02ba4\n" + "hw=prot\n" + "prot_ro_value16=0x400000,-2,0x9000\n" + "prot_ro_value16=0x401000,-2,0xd300\n" + "[]\n" + "check_str=0x104,\" \"\n" + "check_crc32=0xf68f6367\n" + "hw=prot\n" + "prot_ro_value16=0xa13002,-2,0x01\n" + "prot_ro_value16=0xa1303e,-2,0x1f\n" + "[]\n" + "check_str=0x104,\" \"\n" + "check_crc32=0xfb176667\n" + "hw=prot\n" + "prot_ro_value16=0xa13000,-2,0x14\n" + "prot_ro_value16=0xa13002,-2,0x01\n" + "prot_ro_value16=0xa1303e,-2,0x1f\n" + "[]\n" + "check_csum=0\n" + "check_crc32=0x3ee639f0\n" + "hw=prot\n" + "prot_ro_value16=0xa13000,-2,0x0c\n" + "[]\n" + "check_csum=0\n" + "check_crc32=0xdecdf740\n" + "hw=prot\n" + "prot_ro_value16=0x400000,-2,0x5500\n" + "prot_ro_value16=0x400002,-2,0x0f00\n" + "prot_ro_value16=0x400004,-2,0xaa00\n" + "prot_ro_value16=0x400006,-2,0xf000\n" + "[]\n" + "check_str=0x104,\" \"\n" + "check_crc32=0xf26f88d1\n" + "hw=prot\n" + "prot_ro_value16=0x400002,-2,0x9800\n" + "prot_ro_value16=0x400004,-2,0xaa00#or0xc900\n" + "prot_ro_value16=0x400006,-2,0xf000\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0x4820a161\n" + "hw=prot\n" + "prot_ro_value16=0x400000,-2,0x5500\n" + "prot_ro_value16=0x400002,-2,0x0f00\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0x413dfee2\n" + "hw=prot_lk3\n" + "[]\n" + "check_str=0x140,\"SUPER MARIO BROS \"\n" + "hw=prot\n" + "prot_ro_value16=0xa13000,-2,0x0c\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0xf7e1b3e1\n" + "hw=prot\n" + "prot_ro_value16=0xa13000,-2,0x0a\n" + "[]\n" + "check_str=0x104,\" are Registered Trademarks\"\n" + "check_crc32=0xb8261ff5\n" + "hw=prot\n" + "prot_rw_value16=0x400000,0xc00000,0\n" +; diff --git a/waterbox/picodrive/pico/cd/cd_image.c b/waterbox/picodrive/pico/cd/cd_image.c new file mode 100644 index 0000000000..07b55ceb06 --- /dev/null +++ b/waterbox/picodrive/pico/cd/cd_image.c @@ -0,0 +1,268 @@ +/* + * CD image handler + * (C) notaz, 2007,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" +#include "genplus_macros.h" +#include "cdd.h" +#include "cue.h" + +static int handle_mp3(const char *fname, int index) +{ + track_t *track = &cdd.toc.tracks[index]; + FILE *tmp_file; + int kBps; + int fs, ret; + + tmp_file = fopen(fname, "rb"); + if (tmp_file == NULL) + return -1; + + ret = fseek(tmp_file, 0, SEEK_END); + fs = ftell(tmp_file); + fseek(tmp_file, 0, SEEK_SET); + +#ifdef _PSP_FW_VERSION + // some systems (like PSP) can't have many open files at a time, + // so we work with their names instead. + fclose(tmp_file); + tmp_file = (void *) strdup(fname); +#endif + + kBps = mp3_get_bitrate(tmp_file, fs) / 8; + if (ret != 0 || kBps <= 0) + { + elprintf(EL_STATUS, "track %2i: mp3 bitrate %i", index+1, kBps); +#ifdef _PSP_FW_VERSION + free(tmp_file); +#else + fclose(tmp_file); +#endif + return -1; + } + + track->fd = tmp_file; + track->offset = 0; + + fs *= 75; + fs /= kBps * 1000; + return fs; +} + +static void to_upper(char *d, const char *s) +{ + for (; *s != 0; d++, s++) { + if ('a' <= *s && *s <= 'z') + *d = *s - 'a' + 'A'; + else + *d = *s; + } +} + +// cdd.c uses lba - 150 +static void sprintf_lba(char *buf, size_t size, int lba) +{ + lba += 150; + snprintf(buf, size, "%02d:%02d:%02d", lba / 60 / 75, + (lba / 75) % 60, lba % 75); +} + +int load_cd_image(const char *cd_img_name, int *type) +{ + static const char *exts[] = { + "%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3", + "%d.mp3", " %d.mp3", "-%d.mp3", "_%d.mp3", " - %d.mp3", + }; + int i, j, n, lba, index, length, ret; + int iso_name_len, missed, cd_img_sectors; + char tmp_name[256], tmp_ext[10], tmp_ext_u[10]; + track_t *tracks = cdd.toc.tracks; + cue_data_t *cue_data = NULL; + pm_file *pmf; + + if (PicoCDLoadProgressCB != NULL) + PicoCDLoadProgressCB(cd_img_name, 1); + + Pico_mcd->cdda_type = CT_UNKNOWN; + + /* is this a .cue? */ + cue_data = cue_parse(cd_img_name); + if (cue_data != NULL) { + cd_img_name = cue_data->tracks[1].fname; + *type = cue_data->tracks[1].type; + } + + pmf = pm_open(cd_img_name); + if (pmf == NULL) + { + if (cue_data != NULL) + cue_destroy(cue_data); + return -1; + } + tracks[0].fd = pmf; + + if (*type == CT_ISO) + cd_img_sectors = pmf->size >>= 11; // size in sectors + else cd_img_sectors = pmf->size /= 2352; + + // cdd.c operates with lba - 150 + tracks[0].start = 0; + tracks[0].end = cd_img_sectors; + tracks[0].offset = 0; + + sprintf_lba(tmp_ext, sizeof(tmp_ext), 0); + elprintf(EL_STATUS, "Track 1: %s %9i DATA %s", + tmp_ext, tracks[0].end, cd_img_name); + + lba = cd_img_sectors; + + if (cue_data != NULL) + { + if (cue_data->tracks[2].fname == NULL) { + // NULL fname means track2 is in same file as track1 + lba = tracks[0].end = cue_data->tracks[2].sector_offset; + } + i = 100 / cue_data->track_count + 1; // progress display + + for (n = 2; n <= cue_data->track_count; n++) + { + if (PicoCDLoadProgressCB != NULL) + PicoCDLoadProgressCB(cd_img_name, i * n); + + index = n - 1; + lba += cue_data->tracks[n].pregap; + if (cue_data->tracks[n].type == CT_MP3) { + ret = handle_mp3(cue_data->tracks[n].fname, index); + if (ret < 0) + break; + length = ret; + } + else if (cue_data->tracks[n].fname != NULL) + { + pm_file *f = pm_open(cue_data->tracks[n].fname); + if (f != NULL) + { + // assume raw, ignore header for wav.. + tracks[index].fd = f; + tracks[index].offset = cue_data->tracks[n].sector_offset; + length = f->size / 2352; + } + else + { + elprintf(EL_STATUS, "track %2i (%s): can't determine length", + n, cue_data->tracks[n].fname); + tracks[index].offset = 0; + length = 2*75; + } + } + else + { + if (n < cue_data->track_count) + length = cue_data->tracks[n+1].sector_offset - + cue_data->tracks[n].sector_offset; + else + length = cd_img_sectors - cue_data->tracks[n].sector_offset; + tracks[index].offset = cue_data->tracks[n].sector_offset; + } + + if (cue_data->tracks[n].sector_xlength != 0) + // overriden by custom cue command + length = cue_data->tracks[n].sector_xlength; + + Pico_mcd->cdda_type = cue_data->tracks[n].type; + + tracks[index].start = lba; + lba += length; + tracks[index].end = lba; + + sprintf_lba(tmp_ext, sizeof(tmp_ext), tracks[index].start); + elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO %s", + n, tmp_ext, length, cue_data->tracks[n].fname); + } + goto finish; + } + + /* mp3 track autosearch, Gens-like */ + iso_name_len = strlen(cd_img_name); + if (iso_name_len >= sizeof(tmp_name)) + iso_name_len = sizeof(tmp_name) - 1; + + for (n = 2, i = 0, missed = 0; i < 100 && missed < 4; i++) + { + if (PicoCDLoadProgressCB != NULL && i > 1) + PicoCDLoadProgressCB(cd_img_name, i + (100-i)*missed/4); + + for (j = 0; j < sizeof(exts)/sizeof(char *); j++) + { + int ext_len; + char *p; + + index = n - 1; + + snprintf(tmp_ext, sizeof(tmp_ext), exts[j], i); + ext_len = strlen(tmp_ext); + to_upper(tmp_ext_u, tmp_ext); + + memcpy(tmp_name, cd_img_name, iso_name_len + 1); + p = tmp_name + iso_name_len - 4; + + strcpy(p, tmp_ext); + ret = handle_mp3(tmp_name, index); + if (ret <= 0) { + strcpy(p, tmp_ext_u); + ret = handle_mp3(tmp_name, index); + } + + if (ret <= 0 && i > 1 && iso_name_len > ext_len) { + p = tmp_name + iso_name_len - ext_len; + strcpy(p, tmp_ext); + ret = handle_mp3(tmp_name, index); + if (ret <= 0) { + strcpy(p, tmp_ext_u); + ret = handle_mp3(tmp_name, index); + } + } + + if (ret > 0) + { + length = ret; + tracks[index].start = lba; + lba += length; + tracks[index].end = lba; + + Pico_mcd->cdda_type = CT_MP3; + + sprintf_lba(tmp_ext, sizeof(tmp_ext), tracks[index].start); + elprintf(EL_STATUS, "Track %2i: %s %9i AUDIO - %s", + n, tmp_ext, length, tmp_name); + + n++; + missed = 0; + break; + } + } + if (ret <= 0 && i > 1) + missed++; + } + +finish: + cdd.toc.last = n - 1; + cdd.toc.end = lba; + + sprintf_lba(tmp_ext, sizeof(tmp_ext), cdd.toc.end); + elprintf(EL_STATUS, "End CD - %s\n", tmp_ext); + + if (PicoCDLoadProgressCB != NULL) + PicoCDLoadProgressCB(cd_img_name, 100); + + if (cue_data != NULL) + cue_destroy(cue_data); + + return 0; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdc.c b/waterbox/picodrive/pico/cd/cdc.c new file mode 100644 index 0000000000..bf688f5792 --- /dev/null +++ b/waterbox/picodrive/pico/cd/cdc.c @@ -0,0 +1,846 @@ +/*************************************************************************************** + * Genesis Plus + * CD data controller (LC89510 compatible) + * + * Copyright (C) 2012 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + +#include "../pico_int.h" +#include "genplus_macros.h" + +/* IFSTAT register bitmasks */ +#define BIT_DTEI 0x40 +#define BIT_DECI 0x20 +#define BIT_DTBSY 0x08 +#define BIT_DTEN 0x02 + +/* IFCTRL register bitmasks */ +#define BIT_DTEIEN 0x40 +#define BIT_DECIEN 0x20 +#define BIT_DOUTEN 0x02 + +/* CTRL0 register bitmasks */ +#define BIT_DECEN 0x80 +#define BIT_E01RQ 0x20 +#define BIT_AUTORQ 0x10 +#define BIT_WRRQ 0x04 + +/* CTRL1 register bitmasks */ +#define BIT_MODRQ 0x08 +#define BIT_FORMRQ 0x04 +#define BIT_SHDREN 0x01 + +/* CTRL2 register bitmask */ +#define BIT_VALST 0x80 + +/* PicoDrive: doing DMA at once, not using callbacks */ +//#define DMA_BYTES_PER_LINE 512 + +enum dma_type { + word_ram_0_dma_w = 1, + word_ram_1_dma_w = 2, + word_ram_2M_dma_w = 3, + pcm_ram_dma_w = 4, + prg_ram_dma_w = 5, +}; + +/* CDC hardware */ +typedef struct +{ + uint8 ifstat; + uint8 ifctrl; + uint16 dbc; + uint16 dac; + uint16 pt; + uint16 wa; + uint8 ctrl[2]; + uint8 head[2][4]; + uint8 stat[4]; + int cycles; + //void (*dma_w)(unsigned int words); + int dma_w; + uint8 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */ +} cdc_t; + +static cdc_t cdc; + +void cdc_init(void) +{ + memset(&cdc, 0, sizeof(cdc_t)); +} + +void cdc_reset(void) +{ + /* reset CDC register index */ + Pico_mcd->s68k_regs[0x04+1] = 0x00; + + /* reset CDC registers */ + cdc.ifstat = 0xff; + cdc.ifctrl = 0x00; + cdc.ctrl[0] = 0x00; + cdc.ctrl[1] = 0x00; + cdc.stat[0] = 0x00; + cdc.stat[1] = 0x00; + cdc.stat[2] = 0x00; + cdc.stat[3] = 0x80; + cdc.head[0][0] = 0x00; + cdc.head[0][1] = 0x00; + cdc.head[0][2] = 0x00; + cdc.head[0][3] = 0x01; + cdc.head[1][0] = 0x00; + cdc.head[1][1] = 0x00; + cdc.head[1][2] = 0x00; + cdc.head[1][3] = 0x00; + + /* reset CDC cycle counter */ + cdc.cycles = 0; + + /* DMA transfer disabled */ + cdc.dma_w = 0; +} + +int cdc_context_save(uint8 *state) +{ + uint8 tmp8; + int bufferptr = 0; + + if (cdc.dma_w == pcm_ram_dma_w) + { + tmp8 = 1; + } + else if (cdc.dma_w == prg_ram_dma_w) + { + tmp8 = 2; + } + else if (cdc.dma_w == word_ram_0_dma_w) + { + tmp8 = 3; + } + else if (cdc.dma_w == word_ram_1_dma_w) + { + tmp8 = 4; + } + else if (cdc.dma_w == word_ram_2M_dma_w) + { + tmp8 = 5; + } + else + { + tmp8 = 0; + } + + save_param(&cdc, sizeof(cdc)); + save_param(&tmp8, 1); + + return bufferptr; +} + +int cdc_context_load(uint8 *state) +{ + uint8 tmp8; + int bufferptr = 0; + + load_param(&cdc, sizeof(cdc)); + load_param(&tmp8, 1); + + switch (tmp8) + { + case 1: + cdc.dma_w = pcm_ram_dma_w; + break; + case 2: + cdc.dma_w = prg_ram_dma_w; + break; + case 3: + cdc.dma_w = word_ram_0_dma_w; + break; + case 4: + cdc.dma_w = word_ram_1_dma_w; + break; + case 5: + cdc.dma_w = word_ram_2M_dma_w; + break; + default: + cdc.dma_w = 0; + break; + } + + return bufferptr; +} + +int cdc_context_load_old(uint8 *state) +{ +#define old_load(v, ofs) \ + memcpy(&cdc.v, state + ofs, sizeof(cdc.v)) + + memcpy(cdc.ram, state, 0x4000); + old_load(ifstat, 67892); + old_load(ifctrl, 67924); + old_load(dbc, 67896); + old_load(dac, 67900); + old_load(pt, 67908); + old_load(wa, 67912); + old_load(ctrl, 67928); + old_load(head[0], 67904); + old_load(stat, 67916); + + cdc.dma_w = 0; + switch (Pico_mcd->s68k_regs[0x04+0] & 0x07) + { + case 4: /* PCM RAM DMA */ + cdc.dma_w = pcm_ram_dma_w; + break; + case 5: /* PRG-RAM DMA */ + cdc.dma_w = prg_ram_dma_w; + break; + case 7: /* WORD-RAM DMA */ + if (Pico_mcd->s68k_regs[0x02+1] & 0x04) + { + if (Pico_mcd->s68k_regs[0x02+1] & 0x01) + cdc.dma_w = word_ram_0_dma_w; + else + cdc.dma_w = word_ram_1_dma_w; + } + else + { + if (Pico_mcd->s68k_regs[0x02+1] & 0x02) + cdc.dma_w = word_ram_2M_dma_w; + } + break; + } + + return 0x10960; // sizeof(old_cdc) +#undef old_load +} + +static void do_dma(enum dma_type type, int words_in) +{ + int dma_addr = (Pico_mcd->s68k_regs[0x0a] << 8) | Pico_mcd->s68k_regs[0x0b]; + int src_addr = cdc.dac & 0x3ffe; + int dst_addr = dma_addr; + int words = words_in; + int dst_limit = 0; + uint8 *dst; + int len; + + elprintf(EL_CD, "dma %d %04x->%04x %x", + type, cdc.dac, dst_addr, words_in); + + switch (type) + { + case pcm_ram_dma_w: + dst_addr = (dst_addr << 2) & 0xffc; + if (dst_addr + words * 2 > 0x1000) { + elprintf(EL_ANOMALY, "pcm dma oflow: %x %x", dst_addr, words); + words = (0x1000 - dst_addr) / 2; + } + dst = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank]; + dst = dst + dst_addr; + while (words > 0) + { + if (src_addr + words * 2 > 0x4000) { + len = 0x4000 - src_addr; + memcpy(dst, cdc.ram + src_addr, len); + dst += len; + src_addr = 0; + words -= len / 2; + continue; + } + memcpy(dst, cdc.ram + src_addr, words * 2); + break; + } + goto update_dma; + + case prg_ram_dma_w: + dst_addr <<= 3; + dst = Pico_mcd->prg_ram + dst_addr; + dst_limit = 0x80000; + break; + + case word_ram_0_dma_w: + dst_addr = (dst_addr << 3) & 0x1fffe; + dst = Pico_mcd->word_ram1M[0] + dst_addr; + dst_limit = 0x20000; + break; + + case word_ram_1_dma_w: + dst_addr = (dst_addr << 3) & 0x1fffe; + dst = Pico_mcd->word_ram1M[1] + dst_addr; + dst_limit = 0x20000; + break; + + case word_ram_2M_dma_w: + dst_addr = (dst_addr << 3) & 0x3fffe; + dst = Pico_mcd->word_ram2M + dst_addr; + dst_limit = 0x40000; + break; + + default: + elprintf(EL_ANOMALY, "invalid dma: %d", type); + goto update_dma; + } + + if (dst_addr + words * 2 > dst_limit) { + elprintf(EL_ANOMALY, "cd dma %d oflow: %x %x", type, dst_addr, words); + words = (dst_limit - dst_addr) / 2; + } + while (words > 0) + { + if (src_addr + words * 2 > 0x4000) { + len = 0x4000 - src_addr; + memcpy16bswap((void *)dst, cdc.ram + src_addr, len / 2); + dst += len; + src_addr = 0; + words -= len / 2; + continue; + } + memcpy16bswap((void *)dst, cdc.ram + src_addr, words); + break; + } + +update_dma: + /* update DMA addresses */ + cdc.dac += words_in * 2; + if (type == pcm_ram_dma_w) + dma_addr += words_in >> 1; + else + dma_addr += words_in >> 2; + + Pico_mcd->s68k_regs[0x0a] = dma_addr >> 8; + Pico_mcd->s68k_regs[0x0b] = dma_addr; +} + +void cdc_dma_update(void) +{ + /* end of DMA transfer ? */ + //if (cdc.dbc < DMA_BYTES_PER_LINE) + { + /* transfer remaining words using 16-bit DMA */ + //cdc.dma_w((cdc.dbc + 1) >> 1); + do_dma(cdc.dma_w, (cdc.dbc + 1) >> 1); + + /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ + cdc.dbc = 0xf000; + + /* clear !DTEN and !DTBSY */ + cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); + + /* pending Data Transfer End interrupt */ + cdc.ifstat &= ~BIT_DTEI; + + /* Data Transfer End interrupt enabled ? */ + if (cdc.ifctrl & BIT_DTEIEN) + { + /* level 5 interrupt enabled ? */ + if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) + { + /* update IRQ level */ + elprintf(EL_INTS, "cdc DTE irq 5"); + SekInterruptS68k(5); + } + } + + /* clear DSR bit & set EDT bit (SCD register $04) */ + Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80; + + /* disable DMA transfer */ + cdc.dma_w = 0; + } +#if 0 + else + { + /* transfer all words using 16-bit DMA */ + cdc.dma_w(DMA_BYTES_PER_LINE >> 1); + + /* decrement data byte counter */ + cdc.dbc -= length; + } +#endif +} + +int cdc_decoder_update(uint8 header[4]) +{ + /* data decoding enabled ? */ + if (cdc.ctrl[0] & BIT_DECEN) + { + /* update HEAD registers */ + memcpy(cdc.head[0], header, sizeof(cdc.head[0])); + + /* set !VALST */ + cdc.stat[3] = 0x00; + + /* pending decoder interrupt */ + cdc.ifstat &= ~BIT_DECI; + + /* decoder interrupt enabled ? */ + if (cdc.ifctrl & BIT_DECIEN) + { + /* level 5 interrupt enabled ? */ + if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) + { + /* update IRQ level */ + elprintf(EL_INTS, "cdc DEC irq 5"); + SekInterruptS68k(5); + } + } + + /* buffer RAM write enabled ? */ + if (cdc.ctrl[0] & BIT_WRRQ) + { + uint16 offset; + + /* increment block pointer */ + cdc.pt += 2352; + + /* increment write address */ + cdc.wa += 2352; + + /* CDC buffer address */ + offset = cdc.pt & 0x3fff; + + /* write CDD block header (4 bytes) */ + memcpy(cdc.ram + offset, header, 4); + + /* write CDD block data (2048 bytes) */ + cdd_read_data(cdc.ram + 4 + offset); + + /* take care of buffer overrun */ + if (offset > (0x4000 - 2048 - 4)) + { + /* data should be written at the start of buffer */ + memcpy(cdc.ram, cdc.ram + 0x4000, offset + 2048 + 4 - 0x4000); + } + + /* read next data block */ + return 1; + } + } + + /* keep decoding same data block if Buffer Write is disabled */ + return 0; +} + +void cdc_reg_w(unsigned char data) +{ +#ifdef LOG_CDC + elprintf(EL_STATUS, "CDC register %X write 0x%04x", Pico_mcd->s68k_regs[0x04+1] & 0x0F, data); +#endif + switch (Pico_mcd->s68k_regs[0x04+1] & 0x0F) + { + case 0x01: /* IFCTRL */ + { + /* pending interrupts ? */ + if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) || + ((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI))) + { + /* level 5 interrupt enabled ? */ + if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) + { + /* update IRQ level */ + elprintf(EL_INTS, "cdc pending irq 5"); + SekInterruptS68k(5); + } + } + else // if (scd.pending & (1 << 5)) + { + /* clear pending level 5 interrupts */ + SekInterruptClearS68k(5); + } + + /* abort any data transfer if data output is disabled */ + if (!(data & BIT_DOUTEN)) + { + /* clear !DTBSY and !DTEN */ + cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); + } + + cdc.ifctrl = data; + Pico_mcd->s68k_regs[0x04+1] = 0x02; + break; + } + + case 0x02: /* DBCL */ + cdc.dbc &= 0xff00; + cdc.dbc |= data; + Pico_mcd->s68k_regs[0x04+1] = 0x03; + break; + + case 0x03: /* DBCH */ + cdc.dbc &= 0x00ff; + cdc.dbc |= data << 8; + Pico_mcd->s68k_regs[0x04+1] = 0x04; + break; + + case 0x04: /* DACL */ + cdc.dac &= 0xff00; + cdc.dac |= data; + Pico_mcd->s68k_regs[0x04+1] = 0x05; + break; + + case 0x05: /* DACH */ + cdc.dac &= 0x00ff; + cdc.dac |= data << 8; + Pico_mcd->s68k_regs[0x04+1] = 0x06; + break; + + case 0x06: /* DTRG */ + { + /* start data transfer if data output is enabled */ + if (cdc.ifctrl & BIT_DOUTEN) + { + /* set !DTBSY */ + cdc.ifstat &= ~BIT_DTBSY; + + /* clear DBCH bits 4-7 */ + cdc.dbc &= 0x0fff; + + /* clear EDT & DSR bits (SCD register $04) */ + Pico_mcd->s68k_regs[0x04+0] &= 0x07; + + cdc.dma_w = 0; + + /* setup data transfer destination */ + switch (Pico_mcd->s68k_regs[0x04+0] & 0x07) + { + case 2: /* MAIN-CPU host read */ + case 3: /* SUB-CPU host read */ + { + /* set !DTEN */ + cdc.ifstat &= ~BIT_DTEN; + + /* set DSR bit (register $04) */ + Pico_mcd->s68k_regs[0x04+0] |= 0x40; + break; + } + + case 4: /* PCM RAM DMA */ + { + cdc.dma_w = pcm_ram_dma_w; + break; + } + + case 5: /* PRG-RAM DMA */ + { + cdc.dma_w = prg_ram_dma_w; + break; + } + + case 7: /* WORD-RAM DMA */ + { + /* check memory mode */ + if (Pico_mcd->s68k_regs[0x02+1] & 0x04) + { + /* 1M mode */ + if (Pico_mcd->s68k_regs[0x02+1] & 0x01) + { + /* Word-RAM bank 0 is assigned to SUB-CPU */ + cdc.dma_w = word_ram_0_dma_w; + } + else + { + /* Word-RAM bank 1 is assigned to SUB-CPU */ + cdc.dma_w = word_ram_1_dma_w; + } + } + else + { + /* 2M mode */ + if (Pico_mcd->s68k_regs[0x02+1] & 0x02) + { + /* only process DMA if Word-RAM is assigned to SUB-CPU */ + cdc.dma_w = word_ram_2M_dma_w; + } + } + break; + } + + default: /* invalid */ + { + elprintf(EL_ANOMALY, "invalid CDC tranfer destination (%d)", + Pico_mcd->s68k_regs[0x04+0] & 0x07); + break; + } + } + + if (cdc.dma_w) + pcd_event_schedule_s68k(PCD_EVENT_DMA, cdc.dbc / 2); + } + + Pico_mcd->s68k_regs[0x04+1] = 0x07; + break; + } + + case 0x07: /* DTACK */ + { + /* clear pending data transfer end interrupt */ + cdc.ifstat |= BIT_DTEI; + + /* clear DBCH bits 4-7 */ + cdc.dbc &= 0x0fff; + +#if 0 + /* no pending decoder interrupt ? */ + if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN)) + { + /* clear pending level 5 interrupt */ + SekInterruptClearS68k(5); + } +#endif + Pico_mcd->s68k_regs[0x04+1] = 0x08; + break; + } + + case 0x08: /* WAL */ + cdc.wa &= 0xff00; + cdc.wa |= data; + Pico_mcd->s68k_regs[0x04+1] = 0x09; + break; + + case 0x09: /* WAH */ + cdc.wa &= 0x00ff; + cdc.wa |= data << 8; + Pico_mcd->s68k_regs[0x04+1] = 0x0a; + break; + + case 0x0a: /* CTRL0 */ + { + /* set CRCOK bit only if decoding is enabled */ + cdc.stat[0] = data & BIT_DECEN; + + /* update decoding mode */ + if (data & BIT_AUTORQ) + { + /* set MODE bit according to CTRL1 register & clear FORM bit */ + cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ; + } + else + { + /* set MODE & FORM bits according to CTRL1 register */ + cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ); + } + + cdc.ctrl[0] = data; + Pico_mcd->s68k_regs[0x04+1] = 0x0b; + break; + } + + case 0x0b: /* CTRL1 */ + { + /* update decoding mode */ + if (cdc.ctrl[0] & BIT_AUTORQ) + { + /* set MODE bit according to CTRL1 register & clear FORM bit */ + cdc.stat[2] = data & BIT_MODRQ; + } + else + { + /* set MODE & FORM bits according to CTRL1 register */ + cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ); + } + + cdc.ctrl[1] = data; + Pico_mcd->s68k_regs[0x04+1] = 0x0c; + break; + } + + case 0x0c: /* PTL */ + cdc.pt &= 0xff00; + cdc.pt |= data; + Pico_mcd->s68k_regs[0x04+1] = 0x0d; + break; + + case 0x0d: /* PTH */ + cdc.pt &= 0x00ff; + cdc.pt |= data << 8; + Pico_mcd->s68k_regs[0x04+1] = 0x0e; + break; + + case 0x0e: /* CTRL2 (unused) */ + Pico_mcd->s68k_regs[0x04+1] = 0x0f; + break; + + case 0x0f: /* RESET */ + cdc_reset(); + break; + + default: /* by default, SBOUT is not used */ + break; + } +} + +unsigned char cdc_reg_r(void) +{ + switch (Pico_mcd->s68k_regs[0x04+1] & 0x0F) + { + case 0x01: /* IFSTAT */ + Pico_mcd->s68k_regs[0x04+1] = 0x02; + return cdc.ifstat; + + case 0x02: /* DBCL */ + Pico_mcd->s68k_regs[0x04+1] = 0x03; + return cdc.dbc & 0xff; + + case 0x03: /* DBCH */ + Pico_mcd->s68k_regs[0x04+1] = 0x04; + return (cdc.dbc >> 8) & 0xff; + + case 0x04: /* HEAD0 */ + Pico_mcd->s68k_regs[0x04+1] = 0x05; + return cdc.head[cdc.ctrl[1] & BIT_SHDREN][0]; + + case 0x05: /* HEAD1 */ + Pico_mcd->s68k_regs[0x04+1] = 0x06; + return cdc.head[cdc.ctrl[1] & BIT_SHDREN][1]; + + case 0x06: /* HEAD2 */ + Pico_mcd->s68k_regs[0x04+1] = 0x07; + return cdc.head[cdc.ctrl[1] & BIT_SHDREN][2]; + + case 0x07: /* HEAD3 */ + Pico_mcd->s68k_regs[0x04+1] = 0x08; + return cdc.head[cdc.ctrl[1] & BIT_SHDREN][3]; + + case 0x08: /* PTL */ + Pico_mcd->s68k_regs[0x04+1] = 0x09; + return cdc.pt & 0xff; + + case 0x09: /* PTH */ + Pico_mcd->s68k_regs[0x04+1] = 0x0a; + return (cdc.pt >> 8) & 0xff; + + case 0x0a: /* WAL */ + Pico_mcd->s68k_regs[0x04+1] = 0x0b; + return cdc.wa & 0xff; + + case 0x0b: /* WAH */ + Pico_mcd->s68k_regs[0x04+1] = 0x0c; + return (cdc.wa >> 8) & 0xff; + + case 0x0c: /* STAT0 */ + Pico_mcd->s68k_regs[0x04+1] = 0x0d; + return cdc.stat[0]; + + case 0x0d: /* STAT1 (always return 0) */ + Pico_mcd->s68k_regs[0x04+1] = 0x0e; + return 0x00; + + case 0x0e: /* STAT2 */ + Pico_mcd->s68k_regs[0x04+1] = 0x0f; + return cdc.stat[2]; + + case 0x0f: /* STAT3 */ + { + uint8 data = cdc.stat[3]; + + /* clear !VALST (note: this is not 100% correct but BIOS do not seem to care) */ + cdc.stat[3] = BIT_VALST; + + /* clear pending decoder interrupt */ + cdc.ifstat |= BIT_DECI; + +#if 0 + /* no pending data transfer end interrupt */ + if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) + { + /* clear pending level 5 interrupt */ + SekInterruptClearS68k(5); + } +#endif + + Pico_mcd->s68k_regs[0x04+1] = 0x00; + return data; + } + + default: /* by default, COMIN is always empty */ + return 0xff; + } +} + +unsigned short cdc_host_r(void) +{ + /* check if data is available */ + if (!(cdc.ifstat & BIT_DTEN)) + { + /* read data word from CDC RAM buffer */ + uint8 *datap = cdc.ram + (cdc.dac & 0x3ffe); + uint16 data = (datap[0] << 8) | datap[1]; + +#ifdef LOG_CDC + error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac, data, cdc.dbc, s68k.pc); +#endif + + /* increment data address counter */ + cdc.dac += 2; + + /* decrement data byte counter */ + cdc.dbc -= 2; + + /* end of transfer ? */ + if ((int16)cdc.dbc <= 0) + { + /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ + cdc.dbc = 0xf000; + + /* clear !DTEN and !DTBSY */ + cdc.ifstat |= (BIT_DTBSY | BIT_DTEN); + + /* pending Data Transfer End interrupt */ + cdc.ifstat &= ~BIT_DTEI; + + /* Data Transfer End interrupt enabled ? */ + if (cdc.ifctrl & BIT_DTEIEN) + { + /* level 5 interrupt enabled ? */ + if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5) + { + /* update IRQ level */ + elprintf(EL_INTS, "cdc DTE irq 5"); + SekInterruptS68k(5); + } + } + + /* clear DSR bit & set EDT bit (SCD register $04) */ + Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80; + } + + return data; + } + +#ifdef LOG_CDC + error("error reading CDC host (data transfer disabled)\n"); +#endif + return 0xffff; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdd.c b/waterbox/picodrive/pico/cd/cdd.c new file mode 100644 index 0000000000..e0e1ec1c6e --- /dev/null +++ b/waterbox/picodrive/pico/cd/cdd.c @@ -0,0 +1,1278 @@ +/*************************************************************************************** + * Genesis Plus + * CD drive processor & CD-DA fader + * + * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ + +#include "../pico_int.h" +#include "genplus_macros.h" +#include "cue.h" +#include "cdd.h" + +#ifdef USE_LIBTREMOR +#define SUPPORTED_EXT 20 +#else +#define SUPPORTED_EXT 10 +#endif + +cdd_t cdd; + +/* BCD conversion lookup tables */ +static const uint8 lut_BCD_8[100] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, +}; + +static const uint16 lut_BCD_16[100] = +{ + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, + 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, + 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, 0x0209, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, 0x0308, 0x0309, + 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, + 0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, + 0x0600, 0x0601, 0x0602, 0x0603, 0x0604, 0x0605, 0x0606, 0x0607, 0x0608, 0x0609, + 0x0700, 0x0701, 0x0702, 0x0703, 0x0704, 0x0705, 0x0706, 0x0707, 0x0708, 0x0709, + 0x0800, 0x0801, 0x0802, 0x0803, 0x0804, 0x0805, 0x0806, 0x0807, 0x0808, 0x0809, + 0x0900, 0x0901, 0x0902, 0x0903, 0x0904, 0x0905, 0x0906, 0x0907, 0x0908, 0x0909, +}; + +/* pre-build TOC */ +static const uint16 toc_snatcher[21] = +{ + 56014, 495, 10120, 20555, 1580, 5417, 12502, 16090, 6553, 9681, + 8148, 20228, 8622, 6142, 5858, 1287, 7424, 3535, 31697, 2485, + 31380 +}; + +static const uint16 toc_lunar[52] = +{ + 5422, 1057, 7932, 5401, 6380, 6592, 5862, 5937, 5478, 5870, + 6673, 6613, 6429, 4996, 4977, 5657, 3720, 5892, 3140, 3263, + 6351, 5187, 3249, 1464, 1596, 1750, 1751, 6599, 4578, 5205, + 1550, 1827, 2328, 1346, 1569, 1613, 7199, 4928, 1656, 2549, + 1875, 3901, 1850, 2399, 2028, 1724, 4889, 14551, 1184, 2132, + 685, 3167 +}; + +static const uint32 toc_shadow[15] = +{ + 10226, 70054, 11100, 12532, 12444, 11923, 10059, 10167, 10138, 13792, + 11637, 2547, 2521, 3856, 900 +}; + +static const uint32 toc_dungeon[13] = +{ + 2250, 22950, 16350, 24900, 13875, 19950, 13800, 15375, 17400, 17100, + 3325, 6825, 25275 +}; + +static const uint32 toc_ffight[26] = +{ + 11994, 9742, 10136, 9685, 9553, 14588, 9430, 8721, 9975, 9764, + 9704, 12796, 585, 754, 951, 624, 9047, 1068, 817, 9191, 1024, + 14562, 10320, 8627, 3795, 3047 +}; + +static const uint32 toc_ffightj[29] = +{ + 11994, 9752, 10119, 9690, 9567, 14575, 9431, 8731, 9965, 9763, + 9716, 12791, 579, 751, 958, 630, 9050, 1052, 825, 9193, 1026, + 14553, 9834, 10542, 1699, 1792, 1781, 3783, 3052 +}; + +/* supported WAVE file header (16-bit stereo samples @44.1kHz) */ +static const unsigned char waveHeader[32] = +{ + 0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x02,0x00, + 0x44,0xac,0x00,0x00,0x10,0xb1,0x02,0x00,0x04,0x00,0x10,0x00,0x64,0x61,0x74,0x61 +}; + +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES +static void ogg_free(int i) +{ + /* clear OGG file descriptor to prevent file from being closed */ + cdd.toc.tracks[i].vf.datasource = NULL; + + /* close VORBIS file structure */ + ov_clear(&cdd.toc.tracks[i].vf); + + /* indicates that the track is a seekable VORBIS file */ + cdd.toc.tracks[i].vf.seekable = 1; + + /* reset file reading position */ + fseek(cdd.toc.tracks[i].fd, 0, SEEK_SET); +} +#endif +#endif + +void cdd_reset(void) +{ + /* reset cycle counter */ + cdd.cycles = 0; + + /* reset drive access latency */ + cdd.latency = 0; + + /* reset track index */ + cdd.index = 0; + + /* reset logical block address */ + cdd.lba = 0; + + /* reset status */ + cdd.status = NO_DISC; + + /* reset CD-DA fader (full volume) */ + cdd.volume = 0x400; + + /* clear CD-DA output */ + cdd.audio[0] = cdd.audio[1] = 0; +} + +/* FIXME: use cdd_read_audio() instead */ +static void cdd_change_track(int index, int lba) +{ + int i, base, lba_offset, lb_len; + + for (i = index; i > 0; i--) + if (cdd.toc.tracks[i].fd != NULL) + break; + + Pico_mcd->cdda_stream = cdd.toc.tracks[i].fd; + base = cdd.toc.tracks[index].offset; + lba_offset = lba - cdd.toc.tracks[index].start; + lb_len = cdd.toc.tracks[index].end - cdd.toc.tracks[index].start; + + elprintf(EL_CD, "play #%d lba %d base %d", index, lba, base); + + cdda_start_play(base, lba_offset, lb_len); +} + +int cdd_context_save(uint8 *state) +{ + int bufferptr = 0; + + save_param(&cdd.cycles, sizeof(cdd.cycles)); + save_param(&cdd.latency, sizeof(cdd.latency)); + save_param(&cdd.index, sizeof(cdd.index)); + save_param(&cdd.lba, sizeof(cdd.lba)); + save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); + save_param(&cdd.volume, sizeof(cdd.volume)); + save_param(&cdd.status, sizeof(cdd.status)); + + return bufferptr; +} + +int cdd_context_load(uint8 *state) +{ + int lba; + int bufferptr = 0; + +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } +#endif +#endif + + load_param(&cdd.cycles, sizeof(cdd.cycles)); + load_param(&cdd.latency, sizeof(cdd.latency)); + load_param(&cdd.index, sizeof(cdd.index)); + load_param(&cdd.lba, sizeof(cdd.lba)); + load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); + load_param(&cdd.volume, sizeof(cdd.volume)); + load_param(&cdd.status, sizeof(cdd.status)); + + /* adjust current LBA within track limit */ + lba = cdd.lba; + if (lba < cdd.toc.tracks[cdd.index].start) + { + lba = cdd.toc.tracks[cdd.index].start; + } + + /* seek to current track position */ + if (!cdd.index) + { + /* DATA track */ + if (cdd.toc.tracks[0].fd) + { + pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); + } + } +#ifdef USE_LIBTREMOR + else if (cdd.toc.tracks[cdd.index].vf.seekable) + { +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* VORBIS file need to be opened first */ + ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); +#endif + /* VORBIS AUDIO track */ + ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); + } +#endif +#if 0 + else if (cdd.toc.tracks[cdd.index].fd) + { + /* PCM AUDIO track */ + fseek(cdd.toc.tracks[cdd.index].fd, (lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); + } +#else + else + { + cdd_change_track(cdd.index, lba); + } +#endif + + return bufferptr; +} + +int cdd_context_load_old(uint8 *state) +{ + memcpy(&cdd.lba, state + 8, sizeof(cdd.lba)); + return 12 * 4; +} + +int cdd_load(const char *filename, int type) +{ + char header[0x210]; + int ret; + + /* genplus parses cue here, in PD we use our own parser */ + ret = load_cd_image(filename, &type); + if (ret != 0) + return ret; + + /* read first 16 bytes */ + pm_read(header, 0x10, cdd.toc.tracks[0].fd); + + /* look for valid CD image ID string */ + if (memcmp("SEGADISCSYSTEM", header, 14)) + { + /* if not found, read next 16 bytes */ + pm_read(header, 0x10, cdd.toc.tracks[0].fd); + + /* look again for valid CD image ID string */ + if (memcmp("SEGADISCSYSTEM", header, 14)) + { + elprintf(EL_STATUS|EL_ANOMALY, "cd: bad cd image?"); + /* assume bin without security code */ + } + + /* BIN format (2352 bytes data blocks) */ + cdd.sectorSize = 2352; + } + else + { + /* ISO format (2048 bytes data blocks) */ + cdd.sectorSize = 2048; + } + + ret = (type == CT_BIN) ? 2352 : 2048; + if (ret != cdd.sectorSize) + elprintf(EL_STATUS|EL_ANOMALY, "cd: type detection mismatch"); + + /* read CD image header + security code */ + pm_read(header + 0x10, 0x200, cdd.toc.tracks[0].fd); + + /* Simulate audio tracks if none found */ + if (cdd.toc.last == 1) + { + /* Some games require exact TOC infos */ + if (strstr(header + 0x180,"T-95035") != NULL) + { + /* Snatcher */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_snatcher[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 21); + } + else if (strstr(header + 0x180,"T-127015") != NULL) + { + /* Lunar - The Silver Star */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_lunar[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 52); + } + else if (strstr(header + 0x180,"T-113045") != NULL) + { + /* Shadow of the Beast II */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_shadow[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 15); + } + else if (strstr(header + 0x180,"T-143025") != NULL) + { + /* Dungeon Explorer */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_dungeon[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 13); + } + else if (strstr(header + 0x180,"MK-4410") != NULL) + { + /* Final Fight CD (USA, Europe) */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffight[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 26); + } + else if (strstr(header + 0x180,"G-6013") != NULL) + { + /* Final Fight CD (Japan) */ + cdd.toc.last = cdd.toc.end = 0; + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + toc_ffightj[cdd.toc.last]; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while (cdd.toc.last < 29); + } +#if 0 + else + { + /* default TOC (99 tracks & 2s per audio tracks) */ + do + { + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end + 2*75; + cdd.toc.tracks[cdd.toc.last].end = cdd.toc.tracks[cdd.toc.last].start + 2*75; + cdd.toc.end = cdd.toc.tracks[cdd.toc.last].end; + cdd.toc.last++; + } + while ((cdd.toc.last < 99) && (cdd.toc.end < 56*60*75)); + } +#endif + } + + /* Lead-out */ + cdd.toc.tracks[cdd.toc.last].start = cdd.toc.end; + + /* CD loaded */ + cdd.loaded = 1; + + /* disc not scanned yet */ + cdd.status = NO_DISC; + + return 0; +} + +void cdd_read_data(uint8 *dst) +{ + /* only read DATA track sectors */ + if ((cdd.lba >= 0) && (cdd.lba < cdd.toc.tracks[0].end)) + { + /* BIN format ? */ + if (cdd.sectorSize == 2352) + { + /* skip 16-byte header */ + pm_seek(cdd.toc.tracks[0].fd, cdd.lba * 2352 + 16, SEEK_SET); + } + + /* read sector data (Mode 1 = 2048 bytes) */ + pm_read(dst, 2048, cdd.toc.tracks[0].fd); + } +} + +#if 0 +void cdd_read_audio(unsigned int samples) +{ + /* previous audio outputs */ + int16 l = cdd.audio[0]; + int16 r = cdd.audio[1]; + + /* get number of internal clocks (samples) needed */ + samples = blip_clocks_needed(blip[0], samples); + + /* audio track playing ? */ + if (!Pico_mcd->s68k_regs[0x36+0] && cdd.toc.tracks[cdd.index].fd) + { + int i, mul, delta; + + /* current CD-DA fader volume */ + int curVol = cdd.volume; + + /* CD-DA fader volume setup (0-1024) */ + int endVol = Pico_mcd->regs[0x34>>1].w >> 4; + + /* read samples from current block */ +#ifdef USE_LIBTREMOR + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + int len, done = 0; + int16 *ptr = (int16 *) (cdc.ram); + samples = samples * 4; + while (done < samples) + { + len = ov_read(&cdd.toc.tracks[cdd.index].vf, (char *)(cdc.ram + done), samples - done, 0); + if (len <= 0) + { + done = samples; + break; + } + done += len; + } + samples = done / 4; + + /* process 16-bit (host-endian) stereo samples */ + for (i=0; i endVol) + { + /* fade-out */ + curVol--; + } + else if (!curVol) + { + /* audio will remain muted until next setup */ + break; + } + } + } + else +#endif + { +#ifdef LSB_FIRST + int16 *ptr = (int16 *) (cdc.ram); +#else + uint8 *ptr = cdc.ram; +#endif + fread(cdc.ram, 1, samples * 4, cdd.toc.tracks[cdd.index].fd); + + /* process 16-bit (little-endian) stereo samples */ + for (i=0; i endVol) + { + /* fade-out */ + curVol--; + } + else if (!curVol) + { + /* audio will remain muted until next setup */ + break; + } + } + } + + /* save current CD-DA fader volume */ + cdd.volume = curVol; + + /* save last audio output for next frame */ + cdd.audio[0] = l; + cdd.audio[1] = r; + } + else + { + /* no audio output */ + if (l) blip_add_delta_fast(blip[0], 0, -l); + if (r) blip_add_delta_fast(blip[1], 0, -r); + + /* save audio output for next frame */ + cdd.audio[0] = 0; + cdd.audio[1] = 0; + } + + /* end of Blip Buffer timeframe */ + blip_end_frame(blip[0], samples); + blip_end_frame(blip[1], samples); +} +#endif + + +void cdd_update(void) +{ +#ifdef LOG_CDD + error("LBA = %d (track n�%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency); +#endif + + /* seeking disc */ + if (cdd.status == CD_SEEK) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } + + /* drive is ready */ + cdd.status = CD_READY; + } + + /* reading disc */ + else if (cdd.status == CD_PLAY) + { + /* drive latency */ + if (cdd.latency > 0) + { + cdd.latency--; + return; + } + + /* track type */ + if (!cdd.index) + { + /* DATA sector header (CD-ROM Mode 1) */ + uint8 header[4]; + uint32 msf = cdd.lba + 150; + header[0] = lut_BCD_8[(msf / 75) / 60]; + header[1] = lut_BCD_8[(msf / 75) % 60]; + header[2] = lut_BCD_8[(msf % 75)]; + header[3] = 0x01; + + /* data track sector read is controlled by CDC */ + cdd.lba += cdc_decoder_update(header); + } + else if (cdd.index < cdd.toc.last) + { + uint8 header[4] = { 0, }; + + /* check against audio track start index */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].start) + { + /* audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x00; + } + + /* audio blocks are still sent to CDC as well as CD DAC/Fader */ + cdc_decoder_update(header); + + /* next audio block is automatically read */ + cdd.lba++; + } + else + { + /* end of disc */ + cdd.status = CD_END; + return; + } + + /* check end of current track */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } +#endif +#endif + /* play next track */ + cdd.index++; + + /* PAUSE between tracks */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* seek to next audio track start */ +#ifdef USE_LIBTREMOR + if (cdd.toc.tracks[cdd.index].vf.seekable) + { +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* VORBIS file need to be opened first */ + ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); +#endif + ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, -cdd.toc.tracks[cdd.index].offset); + } + else +#endif +#if 0 + if (cdd.toc.tracks[cdd.index].fd) + { + fseek(cdd.toc.tracks[cdd.index].fd, (cdd.toc.tracks[cdd.index].start * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); + } +#else + { + cdd_change_track(cdd.index, cdd.lba); + } +#endif + } + } + + /* scanning disc */ + else if (cdd.status == CD_SCAN) + { + /* fast-forward or fast-rewind */ + cdd.lba += cdd.scanOffset; + + /* check current track limits */ + if (cdd.lba >= cdd.toc.tracks[cdd.index].end) + { +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } +#endif +#endif + /* next track */ + cdd.index++; + + /* skip directly to track start position */ + cdd.lba = cdd.toc.tracks[cdd.index].start; + + /* AUDIO track playing ? */ + if (cdd.status == CD_PLAY) + { + Pico_mcd->s68k_regs[0x36+0] = 0x00; + } + } + else if (cdd.lba < cdd.toc.tracks[cdd.index].start) + { +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } +#endif +#endif + + /* previous track */ + cdd.index--; + + /* skip directly to track end position */ + cdd.lba = cdd.toc.tracks[cdd.index].end; + } + + /* check disc limits */ + if (cdd.index < 0) + { + cdd.index = 0; + cdd.lba = 0; + } + else if (cdd.index >= cdd.toc.last) + { + /* no AUDIO track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* end of disc */ + cdd.index = cdd.toc.last; + cdd.lba = cdd.toc.end; + cdd.status = CD_END; + return; + } + + /* seek to current block */ + if (!cdd.index) + { + /* no AUDIO track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* DATA track */ + pm_seek(cdd.toc.tracks[0].fd, cdd.lba * cdd.sectorSize, SEEK_SET); + } +#ifdef USE_LIBTREMOR + else if (cdd.toc.tracks[cdd.index].vf.seekable) + { +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* check if a new track is being played */ + if (!cdd.toc.tracks[cdd.index].vf.datasource) + { + /* VORBIS file need to be opened first */ + ov_open(cdd.toc.tracks[cdd.index].fd,&cdd.toc.tracks[cdd.index].vf,0,0); + } +#endif + /* VORBIS AUDIO track */ + ov_pcm_seek(&cdd.toc.tracks[cdd.index].vf, (cdd.lba - cdd.toc.tracks[cdd.index].start) * 588 - cdd.toc.tracks[cdd.index].offset); + } +#endif +#if 0 + else if (cdd.toc.tracks[cdd.index].fd) + { + /* PCM AUDIO track */ + fseek(cdd.toc.tracks[cdd.index].fd, (cdd.lba * 2352) - cdd.toc.tracks[cdd.index].offset, SEEK_SET); + } +#else + else + { + cdd_change_track(cdd.index, cdd.lba); + } +#endif + } +} + +#define set_reg16(r, v) { \ + uint16 _v = v; \ + Pico_mcd->s68k_regs[(r)] = _v >> 8; \ + Pico_mcd->s68k_regs[(r)+1] = _v; \ +} + +void cdd_process(void) +{ + /* Process CDD command */ + switch (Pico_mcd->s68k_regs[0x42+0] & 0x0f) + { + case 0x00: /* Drive Status */ + { + /* RS1-RS8 normally unchanged */ + Pico_mcd->s68k_regs[0x38+0] = cdd.status; + + /* unless RS1 indicated invalid track infos */ + if (Pico_mcd->s68k_regs[0x38+1] == 0x0f) + { + /* and SEEK has ended */ + if (cdd.status != CD_SEEK) + { + /* then return valid track infos, e.g current track number in RS2-RS3 (fixes Lunar - The Silver Star) */ + Pico_mcd->s68k_regs[0x38+1] = 0x02; + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); + } + } + break; + } + + case 0x01: /* Stop Drive */ + { + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + set_reg16(0x38, 0x0000); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, 0x000f); + return; + } + + case 0x02: /* Read TOC */ + { + if (cdd.status == NO_DISC) + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* Infos automatically retrieved by CDD processor from Q-Channel */ + /* commands 0x00-0x02 (current block) and 0x03-0x05 (Lead-In) */ + switch (Pico_mcd->s68k_regs[0x44+1]) + { + case 0x00: /* Current Absolute Time (MM:SS:FF) */ + { + int lba = cdd.lba + 150; + set_reg16(0x38, cdd.status << 8); + set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); + set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); + set_reg16(0x3e, lut_BCD_16[(lba%75)]); + Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x01: /* Current Track Relative Time (MM:SS:FF) */ + { + int lba = cdd.lba - cdd.toc.tracks[cdd.index].start; + set_reg16(0x38, (cdd.status << 8) | 0x01); + set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); + set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); + set_reg16(0x3e, lut_BCD_16[(lba%75)]); + Pico_mcd->s68k_regs[0x40+0] = cdd.index ? 0x00 : 0x04; /* Current block flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x02: /* Current Track Number */ + { + set_reg16(0x38, (cdd.status << 8) | 0x02); + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[cdd.index + 1] : 0x0A0A); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); /* Disk Control Code (?) in RS6 */ + Pico_mcd->s68k_regs[0x40+0] = 0x00; + break; + } + + case 0x03: /* Total length (MM:SS:FF) */ + { + int lba = cdd.toc.end + 150; + set_reg16(0x38, (cdd.status << 8) | 0x03); + set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); + set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); + set_reg16(0x3e, lut_BCD_16[(lba%75)]); + Pico_mcd->s68k_regs[0x40+0] = 0x00; + break; + } + + case 0x04: /* First & Last Track Numbers */ + { + set_reg16(0x38, (cdd.status << 8) | 0x04); + set_reg16(0x3a, 0x0001); + set_reg16(0x3c, lut_BCD_16[cdd.toc.last]); + set_reg16(0x3e, 0x0000); /* Drive Version (?) in RS6-RS7 */ + Pico_mcd->s68k_regs[0x40+0] = 0x00; /* Lead-In flags in RS8 (bit0 = mute status, bit1: pre-emphasis status, bit2: track type) */ + break; + } + + case 0x05: /* Track Start Time (MM:SS:FF) */ + { + int track = Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1]; + int lba = cdd.toc.tracks[track-1].start + 150; + set_reg16(0x38, (cdd.status << 8) | 0x05); + set_reg16(0x3a, lut_BCD_16[(lba/75)/60]); + set_reg16(0x3c, lut_BCD_16[(lba/75)%60]); + set_reg16(0x3e, lut_BCD_16[(lba%75)]); + Pico_mcd->s68k_regs[0x40+0] = track % 10; /* Track Number (low digit) */ + if (track == 1) + { + /* RS6 bit 3 is set for the first (DATA) track */ + Pico_mcd->s68k_regs[0x3e + 0] |= 0x08; + } + break; + } + + default: + { +#ifdef LOG_ERROR + error("Unknown CDD Command %02X (%X)\n", Pico_mcd->s68k_regs[0x44+1], s68k.pc); +#endif + return; + } + } + break; + } + + case 0x03: /* Play */ + { + /* reset track index */ + int index = 0; + + /* new LBA position */ + int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + + (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + + (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + + /* CD drive latency */ + if (!cdd.latency) + { + /* Fixes a few games hanging during intro because they expect data to be read with some delay */ + /* Radical Rex needs at least one interrupt delay */ + /* Wolf Team games (Anet Futatabi, Cobra Command, Road Avenger & Time Gal) need at least 6 interrupts delay */ + /* Space Adventure Cobra (2nd morgue scene) needs at least 13 interrupts delay (incl. seek time, so 6 is OK) */ + /* Jeopardy & ESPN Sunday Night NFL are picky about this as well: 10 interrupts delay (+ seek time) seems OK */ + cdd.latency = 10; + } + + /* CD drive seek time */ + /* max. seek time = 1.5 s = 1.5 x 75 = 112.5 CDD interrupts (rounded to 120) for 270000 sectors max on disc. */ + /* Note: This is only a rough approximation since, on real hardware, seek time is much likely not linear and */ + /* latency much larger than above value, but this model works fine for Sonic CD (track 26 playback needs to */ + /* be enough delayed to start in sync with intro sequence, as compared with real hardware recording). */ + if (lba > cdd.lba) + { + cdd.latency += (((lba - cdd.lba) * 120) / 270000); + } + else + { + cdd.latency += (((cdd.lba - lba) * 120) / 270000); + } + + /* update current LBA */ + cdd.lba = lba; + + /* get track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* check if track index has changed */ + if (index != cdd.index) + { + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } + + /* open current track VORBIS file */ + if (cdd.toc.tracks[index].vf.seekable) + { + ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); + } + } +#endif +#endif + + /* update current track index */ + cdd.index = index; + + /* stay within track limits when seeking files */ + if (lba < cdd.toc.tracks[index].start) + { + lba = cdd.toc.tracks[index].start; + } + + /* seek to current block */ + if (!index) + { + /* DATA track */ + pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); + } +#ifdef USE_LIBTREMOR + else if (cdd.toc.tracks[index].vf.seekable) + { + /* VORBIS AUDIO track */ + ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); + } +#endif +#if 0 + else if (cdd.toc.tracks[index].fd) + { + /* PCM AUDIO track */ + fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET); + } +#else + else + { + cdd_change_track(index, lba); + } +#endif + + /* no audio track playing (yet) */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status */ + cdd.status = CD_PLAY; + + /* return track index in RS2-RS3 */ + set_reg16(0x38, (CD_PLAY << 8) | 0x02); + set_reg16(0x3a, (cdd.index < cdd.toc.last) ? lut_BCD_16[index + 1] : 0x0A0A); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + Pico_mcd->s68k_regs[0x40+0] = 0x00; + break; + } + + case 0x04: /* Seek */ + { + /* reset track index */ + int index = 0; + + /* new LBA position */ + int lba = ((Pico_mcd->s68k_regs[0x44+0] * 10 + Pico_mcd->s68k_regs[0x44+1]) * 60 + + (Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 + + (Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150; + + /* CD drive seek time */ + /* We are using similar linear model as above, although still not exactly accurate, */ + /* it works fine for Switch/Panic! intro (Switch needs at least 30 interrupts while */ + /* seeking from 00:05:63 to 24:03:19, Panic! when seeking from 00:05:60 to 24:06:07) */ + if (lba > cdd.lba) + { + cdd.latency = ((lba - cdd.lba) * 120) / 270000; + } + else + { + cdd.latency = ((cdd.lba - lba) * 120) / 270000; + } + + /* update current LBA */ + cdd.lba = lba; + + /* get current track index */ + while ((cdd.toc.tracks[index].end <= lba) && (index < cdd.toc.last)) index++; + +#ifdef USE_LIBTREMOR +#ifdef DISABLE_MANY_OGG_OPEN_FILES + /* check if track index has changed */ + if (index != cdd.index) + { + /* close previous track VORBIS file structure to save memory */ + if (cdd.toc.tracks[cdd.index].vf.datasource) + { + ogg_free(cdd.index); + } + + /* open current track VORBIS file */ + if (cdd.toc.tracks[index].vf.seekable) + { + ov_open(cdd.toc.tracks[index].fd,&cdd.toc.tracks[index].vf,0,0); + } + } +#endif +#endif + + /* update current track index */ + cdd.index = index; + + /* stay within track limits */ + if (lba < cdd.toc.tracks[index].start) + { + lba = cdd.toc.tracks[index].start; + } + + /* seek to current block */ + if (!index) + { + /* DATA track */ + pm_seek(cdd.toc.tracks[0].fd, lba * cdd.sectorSize, SEEK_SET); + } +#ifdef USE_LIBTREMOR + else if (cdd.toc.tracks[index].vf.seekable) + { + /* VORBIS AUDIO track */ + ov_pcm_seek(&cdd.toc.tracks[index].vf, (lba - cdd.toc.tracks[index].start) * 588 - cdd.toc.tracks[index].offset); + } +#endif +#if 0 + else if (cdd.toc.tracks[index].fd) + { + /* PCM AUDIO track */ + fseek(cdd.toc.tracks[index].fd, (lba * 2352) - cdd.toc.tracks[index].offset, SEEK_SET); + } +#endif + + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status */ + cdd.status = CD_SEEK; + + /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */ + set_reg16(0x38, (CD_SEEK << 8) | 0x0f); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f); + return; + } + + case 0x06: /* Pause */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; + break; + } + + case 0x07: /* Resume */ + { + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_PLAY; + break; + } + + case 0x08: /* Forward Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = CD_SCAN_SPEED; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; + break; + } + + case 0x09: /* Rewind Scan */ + { + /* reset scanning direction / speed */ + cdd.scanOffset = -CD_SCAN_SPEED; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_SCAN; + break; + } + + + case 0x0a: /* N-Track Jump Control ? (usually sent before CD_SEEK or CD_PLAY commands) */ + { + /* TC3 corresponds to seek direction (00=forward, FF=reverse) */ + /* TC4-TC7 are related to seek length (4x4 bits i.e parameter values are between -65535 and +65535) */ + /* Maybe related to number of auto-sequenced track jumps/moves for CD DSP (cf. CXD2500BQ datasheet) */ + /* also see US Patent nr. 5222054 for a detailled description of seeking operation using Track Jump */ + + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status (RS1-RS8 unchanged) */ + cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY; + break; + } + + case 0x0c: /* Close Tray */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status */ + cdd.status = cdd.loaded ? CD_STOP : NO_DISC; + + /* RS1-RS8 ignored, expects 0x0 ("no disc" ?) in RS0 once */ + set_reg16(0x38, 0x0000); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, 0x000f); + + if (PicoMCDcloseTray) + PicoMCDcloseTray(); + + return; + } + + case 0x0d: /* Open Tray */ + { + /* no audio track playing */ + Pico_mcd->s68k_regs[0x36+0] = 0x01; + + /* update status (RS1-RS8 ignored) */ + cdd.status = CD_OPEN; + set_reg16(0x38, CD_OPEN << 8); + set_reg16(0x3a, 0x0000); + set_reg16(0x3c, 0x0000); + set_reg16(0x3e, 0x0000); + set_reg16(0x40, ~CD_OPEN & 0x0f); + + if (PicoMCDopenTray) + PicoMCDopenTray(); + return; + } + + default: /* Unknown command */ +#ifdef LOG_CDD + error("Unknown CDD Command !!!\n"); +#endif + Pico_mcd->s68k_regs[0x38+0] = cdd.status; + break; + } + + /* only compute checksum when necessary */ + Pico_mcd->s68k_regs[0x40 + 1] = + ~(Pico_mcd->s68k_regs[0x38 + 0] + Pico_mcd->s68k_regs[0x38 + 1] + + Pico_mcd->s68k_regs[0x3a + 0] + Pico_mcd->s68k_regs[0x3a + 1] + + Pico_mcd->s68k_regs[0x3c + 0] + Pico_mcd->s68k_regs[0x3c + 1] + + Pico_mcd->s68k_regs[0x3e + 0] + Pico_mcd->s68k_regs[0x3e + 1] + + Pico_mcd->s68k_regs[0x40 + 0]) & 0x0f; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/cdd.h b/waterbox/picodrive/pico/cd/cdd.h new file mode 100644 index 0000000000..4789cdb49b --- /dev/null +++ b/waterbox/picodrive/pico/cd/cdd.h @@ -0,0 +1,98 @@ +/*************************************************************************************** + * Genesis Plus + * CD drive processor & CD-DA fader + * + * Copyright (C) 2012-2013 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ +#ifndef _HW_CDD_ +#define _HW_CDD_ + +#ifdef USE_LIBTREMOR +#include "tremor/ivorbisfile.h" +#endif + +/* CDD status */ +#define NO_DISC 0x00 +#define CD_PLAY 0x01 +#define CD_SEEK 0x02 +#define CD_SCAN 0x03 +#define CD_READY 0x04 +#define CD_OPEN 0x05 /* similar to 0x0E ? */ +#define CD_STOP 0x09 +#define CD_END 0x0C + +/* CD blocks scanning speed */ +#define CD_SCAN_SPEED 30 + +#define CD_MAX_TRACKS 100 + +/* CD track */ +typedef struct +{ + void *fd; +#ifdef USE_LIBTREMOR + OggVorbis_File vf; +#endif + int offset; + int start; + int end; +} track_t; + +/* CD TOC */ +typedef struct +{ + int end; + int last; + track_t tracks[CD_MAX_TRACKS]; +} toc_t; + +/* CDD hardware */ +typedef struct +{ + uint32 cycles; + uint32 latency; + int loaded; + int index; + int lba; + int scanOffset; + int volume; + uint8 status; + uint16 sectorSize; + toc_t toc; + int16 audio[2]; +} cdd_t; + +extern cdd_t cdd; + +#endif diff --git a/waterbox/picodrive/pico/cd/cell_map.c b/waterbox/picodrive/pico/cd/cell_map.c new file mode 100644 index 0000000000..d586e946d2 --- /dev/null +++ b/waterbox/picodrive/pico/cd/cell_map.c @@ -0,0 +1,45 @@ +/* + * Convert "cell arrange" address to normal address. + * (C) notaz, 2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +// 64 x32 x16 x8 x4 x4 +static unsigned int cell_map(int celln) +{ + int col, row; + + switch ((celln >> 12) & 7) { // 0-0x8000 + case 0: // x32 cells + case 1: + case 2: + case 3: + col = celln >> 8; + row = celln & 0xff; + break; + case 4: // x16 + case 5: + col = celln >> 7; + row = celln & 0x7f; + row |= 0x10000 >> 8; + break; + case 6: // x8 + col = celln >> 6; + row = celln & 0x3f; + row |= 0x18000 >> 8; + break; + case 7: // x4 + col = celln >> 5; + row = celln & 0x1f; + row |= (celln & 0x7800) >> 6; + break; + default: // never happens, only here to make compiler happy + col = row = 0; + break; + } + + return (col & 0x3f) + row*64; +} + diff --git a/waterbox/picodrive/pico/cd/cue.c b/waterbox/picodrive/pico/cd/cue.c new file mode 100644 index 0000000000..f7c15321cf --- /dev/null +++ b/waterbox/picodrive/pico/cd/cue.c @@ -0,0 +1,35 @@ +/* + * cuefile handling + * (C) notaz, 2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include +#include +#include +#include "cue.h" + +#include "../pico_int.h" +// #define elprintf(w,f,...) printf(f "\n",##__VA_ARGS__); + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif +#ifdef __EPOC32__ +#define snprintf(b,s,...) sprintf(b,##__VA_ARGS__) +#endif + +#define BEGINS(buff,str) (strncmp(buff,str,sizeof(str)-1) == 0) + +void cue_destroy(cue_data_t *data) +{ + int c; + + if (data == NULL) return; + + for (c = data->track_count; c > 0; c--) + if (data->tracks[c].fname != NULL) + free(data->tracks[c].fname); + free(data); +} diff --git a/waterbox/picodrive/pico/cd/cue.h b/waterbox/picodrive/pico/cd/cue.h new file mode 100644 index 0000000000..70ade53de9 --- /dev/null +++ b/waterbox/picodrive/pico/cd/cue.h @@ -0,0 +1,29 @@ + +typedef enum +{ + CT_UNKNOWN = 0, + CT_ISO = 1, /* 2048 B/sector */ + CT_BIN = 2, /* 2352 B/sector */ + CT_MP3 = 3, + CT_WAV = 4 +} cue_track_type; + +typedef struct +{ + char *fname; + int pregap; /* pregap for current track */ + int sector_offset; /* in current file */ + int sector_xlength; + cue_track_type type; +} cue_track; + +typedef struct +{ + int track_count; + cue_track tracks[0]; +} cue_data_t; + + +cue_data_t *cue_parse(const char *fname); +void cue_destroy(cue_data_t *data); + diff --git a/waterbox/picodrive/pico/cd/genplus_macros.h b/waterbox/picodrive/pico/cd/genplus_macros.h new file mode 100644 index 0000000000..8ac5d35b08 --- /dev/null +++ b/waterbox/picodrive/pico/cd/genplus_macros.h @@ -0,0 +1,24 @@ +#undef uint8 +#undef uint16 +#undef uint32 +#undef int8 +#undef int16 +#undef int32 + +#define uint8 unsigned char +#define uint16 unsigned short +#define uint32 unsigned int +#define int8 signed char +#define int16 signed short +#define int32 signed int + +#define READ_BYTE(BASE, ADDR) (BASE)[(ADDR)^1] +#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL) + +#define load_param(param, size) \ + memcpy(param, &state[bufferptr], size); \ + bufferptr += size; + +#define save_param(param, size) \ + memcpy(&state[bufferptr], param, size); \ + bufferptr += size; diff --git a/waterbox/picodrive/pico/cd/gfx.c b/waterbox/picodrive/pico/cd/gfx.c new file mode 100644 index 0000000000..a2c97be032 --- /dev/null +++ b/waterbox/picodrive/pico/cd/gfx.c @@ -0,0 +1,451 @@ +/*************************************************************************************** + * Genesis Plus + * CD graphics processor + * + * Copyright (C) 2012 Eke-Eke (Genesis Plus GX) + * + * Redistribution and use of this code or any derivative works are permitted + * provided that the following conditions are met: + * + * - Redistributions may not be sold, nor may they be used in a commercial + * product or activity. + * + * - Redistributions that are modified from the original source must include the + * complete source code, including the source code for all components used by a + * binary built from the modified sources. However, as a special exception, the + * source code distributed need not include anything that is normally distributed + * (in either source or binary form) with the major components (compiler, kernel, + * and so on) of the operating system on which the executable runs, unless that + * component itself accompanies the executable. + * + * - Redistributions must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************************/ +#include "../pico_int.h" +#include "genplus_macros.h" + +typedef struct +{ + //uint32 cycles; /* current cycles count for graphics operation */ + //uint32 cyclesPerLine; /* current graphics operation timings */ + uint32 dotMask; /* stamp map size mask */ + uint16 *tracePtr; /* trace vector pointer */ + uint16 *mapPtr; /* stamp map table base address */ + uint8 stampShift; /* stamp pixel shift value (related to stamp size) */ + uint8 mapShift; /* stamp map table shift value (related to stamp map size) */ + uint16 bufferOffset; /* image buffer column offset */ + uint32 bufferStart; /* image buffer start index */ + uint32 y_step; /* pico: render line step */ + uint8 lut_prio[4][0x10][0x10]; /* WORD-RAM data writes priority lookup table */ + uint8 lut_pixel[0x200]; /* Graphics operation dot offset lookup table */ + uint8 lut_cell[0x100]; /* Graphics operation stamp offset lookup table */ +} gfx_t; + +static gfx_t gfx; + +static void gfx_schedule(void); + +/***************************************************************/ +/* Rotation / Scaling operation (2M Mode) */ +/***************************************************************/ + +void gfx_init(void) +{ + int i, j; + uint8 mask, row, col, temp; + + memset(&gfx, 0, sizeof(gfx)); + + /* Initialize priority modes lookup table */ + for (i = 0; i < 0x10; i++) + { + for (j = 0; j < 0x10; j++) + { + /* normal */ + gfx.lut_prio[0][i][j] = j; + /* underwrite */ + gfx.lut_prio[1][i][j] = i ? i : j; + /* overwrite */ + gfx.lut_prio[2][i][j] = j ? j : i; + /* invalid */ + gfx.lut_prio[3][i][j] = i; + } + } + + /* Initialize cell lookup table */ + /* table entry = yyxxshrr (8 bits) */ + /* with: yy = cell row (0-3) */ + /* xx = cell column (0-3) */ + /* s = stamp size (0=16x16, 1=32x32) */ + /* hrr = HFLIP & ROTATION bits */ + for (i=0; i<0x100; i++) + { + /* one stamp = 2x2 cells (16x16) or 4x4 cells (32x32) */ + mask = (i & 8) ? 3 : 1; + row = (i >> 6) & mask; + col = (i >> 4) & mask; + + if (i & 4) { col = col ^ mask; } /* HFLIP (always first) */ + if (i & 2) { col = col ^ mask; row = row ^ mask; } /* ROLL1 */ + if (i & 1) { temp = col; col = row ^ mask; row = temp; } /* ROLL0 */ + + /* cell offset (0-3 or 0-15) */ + gfx.lut_cell[i] = row + col * (mask + 1); + } + + /* Initialize pixel lookup table */ + /* table entry = yyyxxxhrr (9 bits) */ + /* with: yyy = pixel row (0-7) */ + /* xxx = pixel column (0-7) */ + /* hrr = HFLIP & ROTATION bits */ + for (i=0; i<0x200; i++) + { + /* one cell = 8x8 pixels */ + row = (i >> 6) & 7; + col = (i >> 3) & 7; + + if (i & 4) { col = col ^ 7; } /* HFLIP (always first) */ + if (i & 2) { col = col ^ 7; row = row ^ 7; } /* ROLL1 */ + if (i & 1) { temp = col; col = row ^ 7; row = temp; } /* ROLL0 */ + + /* pixel offset (0-63) */ + gfx.lut_pixel[i] = col + row * 8; + } +} + +int gfx_context_save(uint8 *state) +{ + uint32 tmp32; + int bufferptr = 0; + + //save_param(&gfx.cycles, sizeof(gfx.cycles)); + //save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); + save_param(&gfx.dotMask, sizeof(gfx.dotMask)); + save_param(&gfx.stampShift, sizeof(gfx.stampShift)); + save_param(&gfx.mapShift, sizeof(gfx.mapShift)); + save_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset)); + save_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); + + tmp32 = (uint8 *)(gfx.tracePtr) - Pico_mcd->word_ram2M; + save_param(&tmp32, 4); + + tmp32 = (uint8 *)(gfx.mapPtr) - Pico_mcd->word_ram2M; + save_param(&tmp32, 4); + + save_param(&gfx.y_step, sizeof(gfx.y_step)); + + return bufferptr; +} + +int gfx_context_load(const uint8 *state) +{ + uint32 tmp32; + int bufferptr = 0; + + //load_param(&gfx.cycles, sizeof(gfx.cycles)); + //load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine)); + load_param(&gfx.dotMask, sizeof(gfx.dotMask)); + load_param(&gfx.stampShift, sizeof(gfx.stampShift)); + load_param(&gfx.mapShift, sizeof(gfx.mapShift)); + load_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset)); + load_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); + + load_param(&tmp32, 4); + gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); + + load_param(&tmp32, 4); + gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32); + + load_param(&gfx.y_step, sizeof(gfx.y_step)); + + return bufferptr; +} + +static void gfx_render(uint32 bufferIndex, uint32 width) +{ + uint8 pixel_in, pixel_out; + uint16 stamp_data; + uint32 stamp_index; + uint32 priority; + + /* pixel map start position for current line (13.3 format converted to 13.11) */ + uint32 xpos = *gfx.tracePtr++ << 8; + uint32 ypos = *gfx.tracePtr++ << 8; + + /* pixel map offset values for current line (5.11 format) */ + uint32 xoffset = (int16) *gfx.tracePtr++; + uint32 yoffset = (int16) *gfx.tracePtr++; + + priority = (Pico_mcd->s68k_regs[2] << 8) | Pico_mcd->s68k_regs[3]; + priority = (priority >> 3) & 0x03; + + /* process all dots */ + while (width--) + { + /* check if stamp map is repeated */ + if (Pico_mcd->s68k_regs[0x58+1] & 0x01) + { + /* stamp map range */ + xpos &= gfx.dotMask; + ypos &= gfx.dotMask; + } + else + { + /* 24-bit range */ + xpos &= 0xffffff; + ypos &= 0xffffff; + } + + /* check if pixel is outside stamp map */ + if ((xpos | ypos) & ~gfx.dotMask) + { + /* force pixel output to 0 */ + pixel_out = 0x00; + } + else + { + /* read stamp map table data */ + stamp_data = gfx.mapPtr[(xpos >> gfx.stampShift) | ((ypos >> gfx.stampShift) << gfx.mapShift)]; + + /* stamp generator base index */ + /* sss ssssssss ccyyyxxx (16x16) or sss sssssscc ccyyyxxx (32x32) */ + /* with: s = stamp number (1 stamp = 16x16 or 32x32 pixels) */ + /* c = cell offset (0-3 for 16x16, 0-15 for 32x32) */ + /* yyy = line offset (0-7) */ + /* xxx = pixel offset (0-7) */ + stamp_index = (stamp_data & 0x7ff) << 8; + + if (stamp_index) + { + /* extract HFLIP & ROTATION bits */ + stamp_data = (stamp_data >> 13) & 7; + + /* cell offset (0-3 or 0-15) */ + /* table entry = yyxxshrr (8 bits) */ + /* with: yy = cell row (0-3) = (ypos >> (11 + 3)) & 3 */ + /* xx = cell column (0-3) = (xpos >> (11 + 3)) & 3 */ + /* s = stamp size (0=16x16, 1=32x32) */ + /* hrr = HFLIP & ROTATION bits */ + stamp_index |= gfx.lut_cell[ + stamp_data | ((Pico_mcd->s68k_regs[0x58+1] & 0x02) << 2 ) + | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6; + + /* pixel offset (0-63) */ + /* table entry = yyyxxxhrr (9 bits) */ + /* with: yyy = pixel row (0-7) = (ypos >> 11) & 7 */ + /* xxx = pixel column (0-7) = (xpos >> 11) & 7 */ + /* hrr = HFLIP & ROTATION bits */ + stamp_index |= gfx.lut_pixel[stamp_data | ((xpos >> 8) & 0x38) | ((ypos >> 5) & 0x1c0)]; + + /* read pixel pair (2 pixels/byte) */ + pixel_out = READ_BYTE(Pico_mcd->word_ram2M, stamp_index >> 1); + + /* extract left or rigth pixel */ + if (stamp_index & 1) + { + pixel_out &= 0x0f; + } + else + { + pixel_out >>= 4; + } + } + else + { + /* stamp 0 is not used: force pixel output to 0 */ + pixel_out = 0x00; + } + } + + /* read out paired pixel data */ + pixel_in = READ_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1); + + /* update left or rigth pixel */ + if (bufferIndex & 1) + { + /* priority mode write */ + pixel_out = gfx.lut_prio[priority][pixel_in & 0x0f][pixel_out]; + + pixel_out |= (pixel_in & 0xf0); + } + else + { + /* priority mode write */ + pixel_out = gfx.lut_prio[priority][pixel_in >> 4][pixel_out]; + + pixel_out = (pixel_out << 4) | (pixel_in & 0x0f); + } + + /* write data to image buffer */ + WRITE_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1, pixel_out); + + /* check current pixel position */ + if ((bufferIndex & 7) != 7) + { + /* next pixel */ + bufferIndex++; + } + else + { + /* next cell: increment image buffer offset by one column (minus 7 pixels) */ + bufferIndex += gfx.bufferOffset; + } + + /* increment pixel position */ + xpos += xoffset; + ypos += yoffset; + } +} + +void gfx_start(unsigned int base) +{ + /* make sure 2M mode is enabled */ + if (!(Pico_mcd->s68k_regs[3] & 0x04)) + { + uint32 mask = 0; + uint32 reg; + + /* trace vector pointer */ + gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + ((base << 2) & 0x3fff8)); + + /* stamps & stamp map size */ + switch ((Pico_mcd->s68k_regs[0x58+1] >> 1) & 0x03) + { + case 0: + gfx.dotMask = 0x07ffff; /* 256x256 dots/map */ + gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */ + gfx.mapShift = 4; /* 16x16 stamps/map */ + mask = 0x3fe00; /* 512 bytes/table */ + break; + + case 1: + gfx.dotMask = 0x07ffff; /* 256x256 dots/map */ + gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */ + gfx.mapShift = 3; /* 8x8 stamps/map */ + mask = 0x3ff80; /* 128 bytes/table */ + break; + + case 2: + gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */ + gfx.stampShift = 11 + 4; /* 16x16 dots/stamps */ + gfx.mapShift = 8; /* 256x256 stamps/map */ + mask = 0x20000; /* 131072 bytes/table */ + break; + + case 3: + gfx.dotMask = 0x7fffff; /* 4096*4096 dots/map */ + gfx.stampShift = 11 + 5; /* 32x32 dots/stamps */ + gfx.mapShift = 7; /* 128x128 stamps/map */ + mask = 0x38000; /* 32768 bytes/table */ + break; + } + + /* stamp map table base address */ + reg = (Pico_mcd->s68k_regs[0x5a] << 8) | Pico_mcd->s68k_regs[0x5b]; + gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + ((reg << 2) & mask)); + + /* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */ + gfx.bufferOffset = (((Pico_mcd->s68k_regs[0x5c+1] & 0x1f) + 1) << 6) - 7; + + /* image buffer start index in dot units (2 pixels/byte) */ + reg = (Pico_mcd->s68k_regs[0x5e] << 8) | Pico_mcd->s68k_regs[0x5f]; + gfx.bufferStart = (reg << 3) & 0x7ffc0; + + /* add image buffer horizontal dot offset */ + gfx.bufferStart += (Pico_mcd->s68k_regs[0x60+1] & 0x3f); + + /* reset GFX chip cycle counter */ + //gfx.cycles = cycles; + + /* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */ + //gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w; + + /* start graphics operation */ + Pico_mcd->s68k_regs[0x58] = 0x80; + + gfx_schedule(); + } +} + +/* PicoDrive specific */ +#define UPDATE_CYCLES 20000 + +static void gfx_schedule(void) +{ + int w, h, cycles; + int y_step; + + w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63]; + h = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65]; + + cycles = 5 * w * h; + if (cycles > UPDATE_CYCLES) + y_step = (UPDATE_CYCLES + 5 * w - 1) / (5 * w); + else + y_step = h; + + gfx.y_step = y_step; + pcd_event_schedule_s68k(PCD_EVENT_GFX, 5 * w * y_step); +} + +void gfx_update(unsigned int cycles) +{ + int lines, lines_reg; + int w; + + if (!(Pico_mcd->s68k_regs[0x58] & 0x80)) + return; + + w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63]; + lines = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65]; + lines_reg = lines - gfx.y_step; + + if (lines_reg <= 0) { + Pico_mcd->s68k_regs[0x58] = 0; + Pico_mcd->s68k_regs[0x64] = + Pico_mcd->s68k_regs[0x65] = 0; + + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) { + elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1"); + SekInterruptS68k(1); + } + } + else { + Pico_mcd->s68k_regs[0x64] = lines_reg >> 8; + Pico_mcd->s68k_regs[0x65] = lines_reg; + + if (lines > gfx.y_step) + lines = gfx.y_step; + + pcd_event_schedule(cycles, PCD_EVENT_GFX, 5 * w * lines); + } + + if (PicoOpt & POPT_EN_MCD_GFX) + { + /* render lines */ + while (lines--) + { + /* process dots to image buffer */ + gfx_render(gfx.bufferStart, w); + + /* increment image buffer start index for next line (8 pixels/line) */ + gfx.bufferStart += 8; + } + } +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/gfx_dma.c b/waterbox/picodrive/pico/cd/gfx_dma.c new file mode 100644 index 0000000000..44fa7ab2f7 --- /dev/null +++ b/waterbox/picodrive/pico/cd/gfx_dma.c @@ -0,0 +1,79 @@ +/* + * PicoDrive + * (C) notaz, 2007 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" + +#include "cell_map.c" + +#ifndef UTYPES_DEFINED +typedef unsigned short u16; +#endif + +// check: Heart of the alien, jaguar xj 220 +PICO_INTERNAL void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc) +{ + unsigned char *base; + unsigned int asrc, a2; + u16 *r; + + base = Pico_mcd->word_ram1M[Pico_mcd->s68k_regs[3]&1]; + + switch (Pico.video.type) + { + case 1: // vram + r = Pico.vram; + for(; len; len--) + { + asrc = cell_map(source >> 2) << 2; + asrc |= source & 2; + // if(a&1) d=(d<<8)|(d>>8); // ?? + r[a>>1] = *(u16 *)(base + asrc); + source += 2; + // AutoIncrement + a=(u16)(a+inc); + } + rendstatus |= PDRAW_SPRITES_MOVED; + break; + + case 3: // cram + Pico.m.dirtyPal = 1; + r = Pico.cram; + for(a2=a&0x7f; len; len--) + { + asrc = cell_map(source >> 2) << 2; + asrc |= source & 2; + r[a2>>1] = *(u16 *)(base + asrc); + source += 2; + // AutoIncrement + a2+=inc; + // good dest? + if(a2 >= 0x80) break; + } + a=(a&0xff00)|a2; + break; + + case 5: // vsram[a&0x003f]=d; + r = Pico.vsram; + for(a2=a&0x7f; len; len--) + { + asrc = cell_map(source >> 2) << 2; + asrc |= source & 2; + r[a2>>1] = *(u16 *)(base + asrc); + source += 2; + // AutoIncrement + a2+=inc; + // good dest? + if(a2 >= 0x80) break; + } + a=(a&0xff00)|a2; + break; + } + // remember addr + Pico.video.addr=(u16)a; +} + diff --git a/waterbox/picodrive/pico/cd/mcd.c b/waterbox/picodrive/pico/cd/mcd.c new file mode 100644 index 0000000000..5ac2a30f0b --- /dev/null +++ b/waterbox/picodrive/pico/cd/mcd.c @@ -0,0 +1,415 @@ +/* + * PicoDrive + * (C) notaz, 2007,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" +#include "../sound/ym2612.h" + +extern unsigned char formatted_bram[4*0x10]; + +static unsigned int mcd_m68k_cycle_mult; +static unsigned int mcd_m68k_cycle_base; +static unsigned int mcd_s68k_cycle_base; + +void (*PicoMCDopenTray)(void) = NULL; +void (*PicoMCDcloseTray)(void) = NULL; + + +PICO_INTERNAL void PicoInitMCD(void) +{ + SekInitS68k(); +} + +PICO_INTERNAL void PicoExitMCD(void) +{ +} + +PICO_INTERNAL void PicoPowerMCD(void) +{ + SekCycleCntS68k = SekCycleAimS68k = 0; + + int fmt_size = sizeof(formatted_bram); + memset(Pico_mcd->prg_ram, 0, sizeof(Pico_mcd->prg_ram)); + memset(Pico_mcd->word_ram2M, 0, sizeof(Pico_mcd->word_ram2M)); + memset(Pico_mcd->pcm_ram, 0, sizeof(Pico_mcd->pcm_ram)); + memset(Pico_mcd->bram, 0, sizeof(Pico_mcd->bram)); + memcpy(Pico_mcd->bram + sizeof(Pico_mcd->bram) - fmt_size, + formatted_bram, fmt_size); + memset(Pico_mcd->s68k_regs, 0, sizeof(Pico_mcd->s68k_regs)); + memset(&Pico_mcd->pcm, 0, sizeof(Pico_mcd->pcm)); + memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m)); + + cdc_init(); + gfx_init(); + + // cold reset state (tested) + Pico_mcd->m.state_flags = PCD_ST_S68K_RST; + Pico_mcd->m.busreq = 2; // busreq on, s68k in reset + Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode, m68k access + memset(Pico_mcd->bios + 0x70, 0xff, 4); +} + +void pcd_soft_reset(void) +{ + elprintf(EL_CD, "cd: soft reset"); + + Pico_mcd->m.s68k_pend_ints = 0; + cdc_reset(); + cdd_reset(); +#ifdef _ASM_CD_MEMORY_C + //PicoMemResetCDdecode(1); // don't have to call this in 2M mode +#endif + + memset(&Pico_mcd->s68k_regs[0x38], 0, 9); + Pico_mcd->s68k_regs[0x38+9] = 0x0f; // default checksum + + pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75); + + // TODO: test if register state/timers change +} + +PICO_INTERNAL int PicoResetMCD(void) +{ + // reset button doesn't affect MCD hardware + + // use SRam.data for RAM cart + if (PicoOpt & POPT_EN_MCD_RAMCART) { + if (SRam.data == NULL) + SRam.data = calloc(1, 0x12000); + } + else if (SRam.data != NULL) { + free(SRam.data); + SRam.data = NULL; + } + SRam.start = SRam.end = 0; // unused + + return 0; +} + +static void SekRunM68kOnce(void) +{ + int cyc_do; + pevt_log_m68k_o(EVT_RUN_START); + + if ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { + SekCycleCnt += cyc_do; + +#if defined(EMU_C68K) + PicoCpuCM68k.cycles = cyc_do; + CycloneRun(&PicoCpuCM68k); + SekCycleCnt -= PicoCpuCM68k.cycles; +#elif defined(EMU_M68K) + SekCycleCnt += m68k_execute(cyc_do) - cyc_do; +#elif defined(EMU_F68K) + SekCycleCnt += fm68k_emulate(cyc_do, 0) - cyc_do; +#endif + } + + SekCyclesLeft = 0; + + SekTrace(0); + pevt_log_m68k_o(EVT_RUN_END); +} + +static void SekRunS68k(unsigned int to) +{ + int cyc_do; + + SekCycleAimS68k = to; + if ((cyc_do = SekCycleAimS68k - SekCycleCntS68k) <= 0) + return; + + if (SekShouldInterrupt()) + Pico_mcd->m.s68k_poll_a = 0; + + SekCycleCntS68k += cyc_do; +#if defined(EMU_C68K) + PicoCpuCS68k.cycles = cyc_do; + CycloneRun(&PicoCpuCS68k); + SekCycleCntS68k -= PicoCpuCS68k.cycles; +#elif defined(EMU_M68K) + m68k_set_context(&PicoCpuMS68k); + SekCycleCntS68k += m68k_execute(cyc_do) - cyc_do; + m68k_set_context(&PicoCpuMM68k); +#elif defined(EMU_F68K) + g_m68kcontext = &PicoCpuFS68k; + SekCycleCntS68k += fm68k_emulate(cyc_do, 0) - cyc_do; + g_m68kcontext = &PicoCpuFM68k; +#endif +} + +static void pcd_set_cycle_mult(void) +{ + // ~1.63 for NTSC, ~1.645 for PAL + if (Pico.m.pal) + mcd_m68k_cycle_mult = ((12500000ull << 16) / (50*312*488)); + else + mcd_m68k_cycle_mult = ((12500000ull << 16) / (60*262*488)) + 1; +} + +unsigned int pcd_cycles_m68k_to_s68k(unsigned int c) +{ + return (long long)c * mcd_m68k_cycle_mult >> 16; +} + +/* events */ +static void pcd_cdc_event(unsigned int now) +{ + // 75Hz CDC update + cdd_update(); + + /* check if a new CDD command has been processed */ + if (!(Pico_mcd->s68k_regs[0x4b] & 0xf0)) + { + /* reset CDD command wait flag */ + Pico_mcd->s68k_regs[0x4b] = 0xf0; + + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { + elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4"); + SekInterruptS68k(4); + } + } + + pcd_event_schedule(now, PCD_EVENT_CDC, 12500000/75); +} + +static void pcd_int3_timer_event(unsigned int now) +{ + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN3) { + elprintf(EL_INTS|EL_CD, "s68k: timer irq 3"); + SekInterruptS68k(3); + } + + if (Pico_mcd->s68k_regs[0x31] != 0) + pcd_event_schedule(now, PCD_EVENT_TIMER3, + Pico_mcd->s68k_regs[0x31] * 384); +} + +static void pcd_dma_event(unsigned int now) +{ + cdc_dma_update(); +} + +typedef void (event_cb)(unsigned int now); + +/* times are in s68k (12.5MHz) cycles */ +unsigned int pcd_event_times[PCD_EVENT_COUNT]; +static unsigned int event_time_next; +static event_cb *pcd_event_cbs[PCD_EVENT_COUNT] = { + [PCD_EVENT_CDC] = pcd_cdc_event, + [PCD_EVENT_TIMER3] = pcd_int3_timer_event, + [PCD_EVENT_GFX] = gfx_update, + [PCD_EVENT_DMA] = pcd_dma_event, +}; + +void pcd_event_schedule(unsigned int now, enum pcd_event event, int after) +{ + unsigned int when; + + when = now + after; + if (when == 0) { + // event cancelled + pcd_event_times[event] = 0; + return; + } + + when |= 1; + + elprintf(EL_CD, "cd: new event #%u %u->%u", event, now, when); + pcd_event_times[event] = when; + + if (event_time_next == 0 || CYCLES_GT(event_time_next, when)) + event_time_next = when; +} + +void pcd_event_schedule_s68k(enum pcd_event event, int after) +{ + if (SekCyclesLeftS68k > after) + SekEndRunS68k(after); + + pcd_event_schedule(SekCyclesDoneS68k(), event, after); +} + +static void pcd_run_events(unsigned int until) +{ + int oldest, oldest_diff, time; + int i, diff; + + while (1) { + oldest = -1, oldest_diff = 0x7fffffff; + + for (i = 0; i < PCD_EVENT_COUNT; i++) { + if (pcd_event_times[i]) { + diff = pcd_event_times[i] - until; + if (diff < oldest_diff) { + oldest_diff = diff; + oldest = i; + } + } + } + + if (oldest_diff <= 0) { + time = pcd_event_times[oldest]; + pcd_event_times[oldest] = 0; + elprintf(EL_CD, "cd: run event #%d %u", oldest, time); + pcd_event_cbs[oldest](time); + } + else if (oldest_diff < 0x7fffffff) { + event_time_next = pcd_event_times[oldest]; + break; + } + else { + event_time_next = 0; + break; + } + } + + if (oldest != -1) + elprintf(EL_CD, "cd: next event #%d at %u", + oldest, event_time_next); +} + +int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync) +{ + #define now SekCycleCntS68k + unsigned int s68k_target; + unsigned int target; + + target = m68k_target - mcd_m68k_cycle_base; + s68k_target = mcd_s68k_cycle_base + + ((unsigned long long)target * mcd_m68k_cycle_mult >> 16); + + elprintf(EL_CD, "s68k sync to %u, %u->%u", + m68k_target, now, s68k_target); + + if (Pico_mcd->m.busreq != 1) { /* busreq/reset */ + SekCycleCntS68k = SekCycleAimS68k = s68k_target; + pcd_run_events(m68k_target); + return 0; + } + + while (CYCLES_GT(s68k_target, now)) { + if (event_time_next && CYCLES_GE(now, event_time_next)) + pcd_run_events(now); + + target = s68k_target; + if (event_time_next && CYCLES_GT(target, event_time_next)) + target = event_time_next; + + SekRunS68k(target); + if (m68k_poll_sync && Pico_mcd->m.m68k_poll_cnt == 0) + break; + } + + return s68k_target - now; + #undef now +} + +#define pcd_run_cpus_normal pcd_run_cpus +//#define pcd_run_cpus_lockstep pcd_run_cpus + +static void SekSyncM68k(void); + +void pcd_run_cpus_normal(int m68k_cycles) +{ + SekCycleAim += m68k_cycles; + if (SekShouldInterrupt() || Pico_mcd->m.m68k_poll_cnt < 12) + Pico_mcd->m.m68k_poll_cnt = 0; + else if (Pico_mcd->m.m68k_poll_cnt >= 16) { + int s68k_left = pcd_sync_s68k(SekCycleAim, 1); + if (s68k_left <= 0) { + elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x", + Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc); + SekCycleCnt = SekCycleAim; + return; + } + SekCycleCnt = SekCycleAim - (s68k_left * 40220 >> 16); + } + + while (CYCLES_GT(SekCycleAim, SekCycleCnt)) { + SekRunM68kOnce(); + if (Pico_mcd->m.need_sync) { + Pico_mcd->m.need_sync = 0; + pcd_sync_s68k(SekCycleCnt, 0); + } + } +} + +void pcd_run_cpus_lockstep(int m68k_cycles) +{ + unsigned int target = SekCycleAim + m68k_cycles; + do { + SekCycleAim += 8; + SekSyncM68k(); + pcd_sync_s68k(SekCycleAim, 0); + } while (CYCLES_GT(target, SekCycleAim)); + + SekCycleAim = target; +} + +#define PICO_CD +#define CPUS_RUN(m68k_cycles) \ + pcd_run_cpus(m68k_cycles) + +#include "../pico_cmn.inc" + + +void pcd_prepare_frame(void) +{ + pcd_set_cycle_mult(); + + // need this because we can't have direct mapping between + // master<->slave cycle counters because of overflows + mcd_m68k_cycle_base = SekCycleAim; + mcd_s68k_cycle_base = SekCycleAimS68k; +} + +PICO_INTERNAL void PicoFrameMCD(void) +{ + PicoFrameStart(); + + pcd_prepare_frame(); + PicoFrameHints(); +} + +void pcd_state_loaded(void) +{ + unsigned int cycles; + int diff; + + pcd_set_cycle_mult(); + pcd_state_loaded_mem(); + + memset(Pico_mcd->pcm_mixbuf, 0, sizeof(Pico_mcd->pcm_mixbuf)); + Pico_mcd->pcm_mixbuf_dirty = 0; + Pico_mcd->pcm_mixpos = 0; + Pico_mcd->pcm_regs_dirty = 1; + + // old savestates.. + cycles = pcd_cycles_m68k_to_s68k(SekCycleAim); + diff = cycles - SekCycleAimS68k; + if (diff < -1000 || diff > 1000) { + SekCycleCntS68k = SekCycleAimS68k = cycles; + } + if (pcd_event_times[PCD_EVENT_CDC] == 0) { + pcd_event_schedule(SekCycleAimS68k, PCD_EVENT_CDC, 12500000/75); + + if (Pico_mcd->s68k_regs[0x31]) + pcd_event_schedule(SekCycleAimS68k, PCD_EVENT_TIMER3, + Pico_mcd->s68k_regs[0x31] * 384); + } + + diff = cycles - Pico_mcd->pcm.update_cycles; + if ((unsigned int)diff > 12500000/50) + Pico_mcd->pcm.update_cycles = cycles; + + // reschedule + event_time_next = 0; + pcd_run_events(SekCycleCntS68k); +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/memory.c b/waterbox/picodrive/pico/cd/memory.c new file mode 100644 index 0000000000..e660e35bc5 --- /dev/null +++ b/waterbox/picodrive/pico/cd/memory.c @@ -0,0 +1,1260 @@ +/* + * Memory I/O handlers for Sega/Mega CD. + * (C) notaz, 2007-2009 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" +#include "../memory.h" + +uptr s68k_read8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr s68k_read16_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr s68k_write8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr s68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; + +MAKE_68K_READ8(s68k_read8, s68k_read8_map) +MAKE_68K_READ16(s68k_read16, s68k_read16_map) +MAKE_68K_READ32(s68k_read32, s68k_read16_map) +MAKE_68K_WRITE8(s68k_write8, s68k_write8_map) +MAKE_68K_WRITE16(s68k_write16, s68k_write16_map) +MAKE_68K_WRITE32(s68k_write32, s68k_write16_map) + +// ----------------------------------------------------------------- + +// provided by ASM code: +#ifdef _ASM_CD_MEMORY_C +u32 PicoReadS68k8_pr(u32 a); +u32 PicoReadS68k16_pr(u32 a); +void PicoWriteS68k8_pr(u32 a, u32 d); +void PicoWriteS68k16_pr(u32 a, u32 d); + +u32 PicoReadM68k8_cell0(u32 a); +u32 PicoReadM68k8_cell1(u32 a); +u32 PicoReadM68k16_cell0(u32 a); +u32 PicoReadM68k16_cell1(u32 a); +void PicoWriteM68k8_cell0(u32 a, u32 d); +void PicoWriteM68k8_cell1(u32 a, u32 d); +void PicoWriteM68k16_cell0(u32 a, u32 d); +void PicoWriteM68k16_cell1(u32 a, u32 d); + +u32 PicoReadS68k8_dec0(u32 a); +u32 PicoReadS68k8_dec1(u32 a); +u32 PicoReadS68k16_dec0(u32 a); +u32 PicoReadS68k16_dec1(u32 a); +void PicoWriteS68k8_dec_m0b0(u32 a, u32 d); +void PicoWriteS68k8_dec_m1b0(u32 a, u32 d); +void PicoWriteS68k8_dec_m2b0(u32 a, u32 d); +void PicoWriteS68k8_dec_m0b1(u32 a, u32 d); +void PicoWriteS68k8_dec_m1b1(u32 a, u32 d); +void PicoWriteS68k8_dec_m2b1(u32 a, u32 d); +void PicoWriteS68k16_dec_m0b0(u32 a, u32 d); +void PicoWriteS68k16_dec_m1b0(u32 a, u32 d); +void PicoWriteS68k16_dec_m2b0(u32 a, u32 d); +void PicoWriteS68k16_dec_m0b1(u32 a, u32 d); +void PicoWriteS68k16_dec_m1b1(u32 a, u32 d); +void PicoWriteS68k16_dec_m2b1(u32 a, u32 d); +#endif + +static void remap_prg_window(u32 r1, u32 r3); +static void remap_word_ram(u32 r3); + +// poller detection +#define POLL_LIMIT 16 +#define POLL_CYCLES 64 + +void m68k_comm_check(u32 a) +{ + pcd_sync_s68k(SekCyclesDone(), 0); + if (a >= 0x0e && !Pico_mcd->m.need_sync) { + // there are cases when slave updates comm and only switches RAM + // over after that (mcd1b), so there must be a resync.. + SekEndRun(64); + Pico_mcd->m.need_sync = 1; + } + if (SekNotPolling || a != Pico_mcd->m.m68k_poll_a) { + Pico_mcd->m.m68k_poll_a = a; + Pico_mcd->m.m68k_poll_cnt = 0; + SekNotPolling = 0; + return; + } + Pico_mcd->m.m68k_poll_cnt++; +} + +#ifndef _ASM_CD_MEMORY_C +static u32 m68k_reg_read16(u32 a) +{ + u32 d = 0; + a &= 0x3e; + + switch (a) { + case 0: + // here IFL2 is always 0, just like in Gens + d = ((Pico_mcd->s68k_regs[0x33] << 13) & 0x8000) + | Pico_mcd->m.busreq; + goto end; + case 2: + m68k_comm_check(a); + d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7); + elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc); + goto end; + case 4: + d = Pico_mcd->s68k_regs[4]<<8; + goto end; + case 6: + d = *(u16 *)(Pico_mcd->bios + 0x72); + goto end; + case 8: + d = cdc_host_r(); + goto end; + case 0xA: + elprintf(EL_UIO, "m68k FIXME: reserved read"); + goto end; + case 0xC: // 384 cycle stopwatch timer + // ugh.. + d = pcd_cycles_m68k_to_s68k(SekCyclesDone()); + d = (d - Pico_mcd->m.stopwatch_base_c) / 384; + d &= 0x0fff; + elprintf(EL_CDREGS, "m68k stopwatch timer read (%04x)", d); + goto end; + } + + if (a < 0x30) { + // comm flag/cmd/status (0xE-0x2F) + m68k_comm_check(a); + d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; + goto end; + } + + elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a); + +end: + return d; +} +#endif + +#ifndef _ASM_CD_MEMORY_C +static +#endif +void m68k_reg_write8(u32 a, u32 d) +{ + u32 dold; + a &= 0x3f; + + switch (a) { + case 0: + d &= 1; + if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) { + elprintf(EL_INTS, "m68k: s68k irq 2"); + pcd_sync_s68k(SekCyclesDone(), 0); + SekInterruptS68k(2); + } + return; + case 1: + d &= 3; + dold = Pico_mcd->m.busreq; + if (!(d & 1)) + d |= 2; // verified: can't release bus on reset + if (dold == d) + return; + + pcd_sync_s68k(SekCyclesDone(), 0); + + if ((dold ^ d) & 1) + elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1)); + if (!(d & 1)) + Pico_mcd->m.state_flags |= PCD_ST_S68K_RST; + else if (d == 1 && (Pico_mcd->m.state_flags & PCD_ST_S68K_RST)) { + Pico_mcd->m.state_flags &= ~PCD_ST_S68K_RST; + elprintf(EL_CDREGS, "m68k: resetting s68k"); + SekResetS68k(); + } + if ((dold ^ d) & 2) { + elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1); + remap_prg_window(d, Pico_mcd->s68k_regs[3]); + } + Pico_mcd->m.busreq = d; + return; + case 2: + elprintf(EL_CDREGS, "m68k: prg wp=%02x", d); + Pico_mcd->s68k_regs[2] = d; // really use s68k side register + return; + case 3: + dold = Pico_mcd->s68k_regs[3]; + elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc); + if ((d ^ dold) & 0xc0) { + elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", + (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3)); + remap_prg_window(Pico_mcd->m.busreq, d); + } + + // 2M mode state is tracked regardless of current mode + if (d & 2) { + Pico_mcd->m.dmna_ret_2m |= 2; + Pico_mcd->m.dmna_ret_2m &= ~1; + } + if (dold & 4) { // 1M mode + d ^= 2; // 0 sets DMNA, 1 does nothing + d = (d & 0xc2) | (dold & 0x1f); + } + else + d = (d & 0xc0) | (dold & 0x1c) | Pico_mcd->m.dmna_ret_2m; + + goto write_comm; + case 6: + Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer + return; + case 7: + Pico_mcd->bios[0x72] = d; + elprintf(EL_CDREGS, "hint vector set to %04x%04x", + ((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]); + return; + case 0x0f: + a = 0x0e; + case 0x0e: + goto write_comm; + } + + if ((a&0xf0) == 0x10) + goto write_comm; + + elprintf(EL_UIO, "m68k FIXME: invalid write? [%02x] %02x", a, d); + return; + +write_comm: + if (d == Pico_mcd->s68k_regs[a]) + return; + + pcd_sync_s68k(SekCyclesDone(), 0); + Pico_mcd->s68k_regs[a] = d; + if (Pico_mcd->m.s68k_poll_a == (a & ~1)) + { + if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) { + elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a); + SekSetStopS68k(0); + } + Pico_mcd->m.s68k_poll_a = 0; + } +} + +u32 s68k_poll_detect(u32 a, u32 d) +{ +#ifdef USE_POLL_DETECT + u32 cycles, cnt = 0; + if (SekIsStoppedS68k()) + return d; + + cycles = SekCyclesDoneS68k(); + if (!SekNotPolling && a == Pico_mcd->m.s68k_poll_a) { + u32 clkdiff = cycles - Pico_mcd->m.s68k_poll_clk; + if (clkdiff <= POLL_CYCLES) { + cnt = Pico_mcd->m.s68k_poll_cnt + 1; + //printf("-- diff: %u, cnt = %i\n", clkdiff, cnt); + if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) { + SekSetStopS68k(1); + elprintf(EL_CDPOLL, "s68k poll detected @%06x, a=%02x", + SekPcS68k, a); + } + } + } + Pico_mcd->m.s68k_poll_a = a; + Pico_mcd->m.s68k_poll_clk = cycles; + Pico_mcd->m.s68k_poll_cnt = cnt; + SekNotPollingS68k = 0; +#endif + return d; +} + +#define READ_FONT_DATA(basemask) \ +{ \ + unsigned int fnt = *(unsigned int *)(Pico_mcd->s68k_regs + 0x4c); \ + unsigned int col0 = (fnt >> 8) & 0x0f, col1 = (fnt >> 12) & 0x0f; \ + if (fnt & (basemask << 0)) d = col1 ; else d = col0; \ + if (fnt & (basemask << 1)) d |= col1 << 4; else d |= col0 << 4; \ + if (fnt & (basemask << 2)) d |= col1 << 8; else d |= col0 << 8; \ + if (fnt & (basemask << 3)) d |= col1 << 12; else d |= col0 << 12; \ +} + + +#ifndef _ASM_CD_MEMORY_C +static +#endif +u32 s68k_reg_read16(u32 a) +{ + u32 d=0; + + switch (a) { + case 0: + return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state + case 2: + d = (Pico_mcd->s68k_regs[2]<<8) | (Pico_mcd->s68k_regs[3]&0x1f); + elprintf(EL_CDREG3, "s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k); + return s68k_poll_detect(a, d); + case 6: + return cdc_reg_r(); + case 8: + return cdc_host_r(); + case 0xC: + d = SekCyclesDoneS68k() - Pico_mcd->m.stopwatch_base_c; + d /= 384; + d &= 0x0fff; + elprintf(EL_CDREGS, "s68k stopwatch timer read (%04x)", d); + return d; + case 0x30: + elprintf(EL_CDREGS, "s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]); + return Pico_mcd->s68k_regs[31]; + case 0x34: // fader + return 0; // no busy bit + case 0x50: // font data (check: Lunar 2, Silpheed) + READ_FONT_DATA(0x00100000); + return d; + case 0x52: + READ_FONT_DATA(0x00010000); + return d; + case 0x54: + READ_FONT_DATA(0x10000000); + return d; + case 0x56: + READ_FONT_DATA(0x01000000); + return d; + } + + d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1]; + + if (a >= 0x0e && a < 0x30) + return s68k_poll_detect(a, d); + + return d; +} + +#ifndef _ASM_CD_MEMORY_C +static +#endif +void s68k_reg_write8(u32 a, u32 d) +{ + // Warning: d might have upper bits set + switch (a) { + case 1: + if (!(d & 1)) + pcd_soft_reset(); + return; + case 2: + return; // only m68k can change WP + case 3: { + int dold = Pico_mcd->s68k_regs[3]; + elprintf(EL_CDREG3, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k); + d &= 0x1d; + d |= dold & 0xc2; + + // 2M mode state + if (d & 1) { + Pico_mcd->m.dmna_ret_2m |= 1; + Pico_mcd->m.dmna_ret_2m &= ~2; // DMNA clears + } + + if (d & 4) + { + if (!(dold & 4)) { + elprintf(EL_CDREG3, "wram mode 2M->1M"); + wram_2M_to_1M(Pico_mcd->word_ram2M); + } + + if ((d ^ dold) & 0x1d) + remap_word_ram(d); + + if ((d ^ dold) & 0x05) + d &= ~2; // clear DMNA - swap complete + } + else + { + if (dold & 4) { + elprintf(EL_CDREG3, "wram mode 1M->2M"); + wram_1M_to_2M(Pico_mcd->word_ram2M); + remap_word_ram(d); + } + d = (d & ~3) | Pico_mcd->m.dmna_ret_2m; + } + goto write_comm; + } + case 4: + elprintf(EL_CDREGS, "s68k CDC dest: %x", d&7); + Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode + return; + case 5: + //dprintf("s68k CDC reg addr: %x", d&0xf); + break; + case 7: + cdc_reg_w(d & 0xff); + return; + case 0xa: + elprintf(EL_CDREGS, "s68k set CDC dma addr"); + break; + case 0xc: + case 0xd: // 384 cycle stopwatch timer + elprintf(EL_CDREGS|EL_CD, "s68k clear stopwatch (%x)", d); + // does this also reset internal 384 cycle counter? + Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k(); + return; + case 0x0e: + a = 0x0f; + case 0x0f: + goto write_comm; + case 0x31: // 384 cycle int3 timer + d &= 0xff; + elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d); + Pico_mcd->s68k_regs[a] = (u8) d; + if (d) // d or d+1?? + pcd_event_schedule_s68k(PCD_EVENT_TIMER3, d * 384); + else + pcd_event_schedule(0, PCD_EVENT_TIMER3, 0); + break; + case 0x33: // IRQ mask + elprintf(EL_CDREGS|EL_CD, "s68k irq mask: %02x", d); + d &= 0x7e; + if ((d ^ Pico_mcd->s68k_regs[0x33]) & d & PCDS_IEN4) { + // XXX: emulate pending irq instead? + if (Pico_mcd->s68k_regs[0x37] & 4) { + elprintf(EL_INTS, "cdd export irq 4 (unmask)"); + SekInterruptS68k(4); + } + } + break; + case 0x34: // fader + Pico_mcd->s68k_regs[a] = (u8) d & 0x7f; + return; + case 0x36: + return; // d/m bit is unsetable + case 0x37: { + u32 d_old = Pico_mcd->s68k_regs[0x37]; + Pico_mcd->s68k_regs[0x37] = d & 7; + if ((d&4) && !(d_old&4)) { + // ?? + pcd_event_schedule_s68k(PCD_EVENT_CDC, 12500000/75); + + if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) { + elprintf(EL_INTS, "cdd export irq 4"); + SekInterruptS68k(4); + } + } + return; + } + case 0x4b: + Pico_mcd->s68k_regs[a] = 0; // (u8) d; ? + cdd_process(); + { + static const char *nm[] = + { "stat", "stop", "read_toc", "play", + "seek", "???", "pause", "resume", + "ff", "fr", "tjump", "???", + "close","open", "???", "???" }; + u8 *c = &Pico_mcd->s68k_regs[0x42]; + u8 *s = &Pico_mcd->s68k_regs[0x38]; + elprintf(EL_CD, + "CDD command: %02x %02x %02x %02x %02x %02x %02x %02x %12s", + c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7], nm[c[0] & 0x0f]); + elprintf(EL_CD, + "CDD status: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9]); + } + return; + case 0x58: + return; + } + + if ((a&0x1f0) == 0x20) + goto write_comm; + + if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42)) + { + elprintf(EL_UIO, "s68k FIXME: invalid write @ %02x?", a); + return; + } + + Pico_mcd->s68k_regs[a] = (u8) d; + return; + +write_comm: + Pico_mcd->s68k_regs[a] = (u8) d; + if (Pico_mcd->m.m68k_poll_cnt) + SekEndRunS68k(0); + Pico_mcd->m.m68k_poll_cnt = 0; +} + +void s68k_reg_write16(u32 a, u32 d) +{ + u8 *r = Pico_mcd->s68k_regs; + + if ((a & 0x1f0) == 0x20) + goto write_comm; + + switch (a) { + case 0x0e: + // special case, 2 byte writes would be handled differently + // TODO: verify + r[0xf] = d; + return; + case 0x58: // stamp data size + r[0x59] = d & 7; + return; + case 0x5a: // stamp map base address + r[0x5a] = d >> 8; + r[0x5b] = d & 0xe0; + return; + case 0x5c: // V cell size + r[0x5d] = d & 0x1f; + return; + case 0x5e: // image buffer start address + r[0x5e] = d >> 8; + r[0x5f] = d & 0xf8; + return; + case 0x60: // image buffer offset + r[0x61] = d & 0x3f; + return; + case 0x62: // h dot size + r[0x62] = (d >> 8) & 1; + r[0x63] = d; + return; + case 0x64: // v dot size + r[0x65] = d; + return; + case 0x66: // trace vector base address + d &= 0xfffe; + r[0x66] = d >> 8; + r[0x67] = d; + gfx_start(d); + return; + default: + break; + } + + s68k_reg_write8(a, d >> 8); + s68k_reg_write8(a + 1, d & 0xff); + return; + +write_comm: + r[a] = d >> 8; + r[a + 1] = d; + if (Pico_mcd->m.m68k_poll_cnt) + SekEndRunS68k(0); + Pico_mcd->m.m68k_poll_cnt = 0; +} + +// ----------------------------------------------------------------- +// Main 68k +// ----------------------------------------------------------------- + +#ifndef _ASM_CD_MEMORY_C +#include "cell_map.c" + +// WORD RAM, cell aranged area (220000 - 23ffff) +static u32 PicoReadM68k8_cell0(u32 a) +{ + a = (a&3) | (cell_map(a >> 2) << 2); // cell arranged + return Pico_mcd->word_ram1M[0][a ^ 1]; +} + +static u32 PicoReadM68k8_cell1(u32 a) +{ + a = (a&3) | (cell_map(a >> 2) << 2); + return Pico_mcd->word_ram1M[1][a ^ 1]; +} + +static u32 PicoReadM68k16_cell0(u32 a) +{ + a = (a&2) | (cell_map(a >> 2) << 2); + return *(u16 *)(Pico_mcd->word_ram1M[0] + a); +} + +static u32 PicoReadM68k16_cell1(u32 a) +{ + a = (a&2) | (cell_map(a >> 2) << 2); + return *(u16 *)(Pico_mcd->word_ram1M[1] + a); +} + +static void PicoWriteM68k8_cell0(u32 a, u32 d) +{ + a = (a&3) | (cell_map(a >> 2) << 2); + Pico_mcd->word_ram1M[0][a ^ 1] = d; +} + +static void PicoWriteM68k8_cell1(u32 a, u32 d) +{ + a = (a&3) | (cell_map(a >> 2) << 2); + Pico_mcd->word_ram1M[1][a ^ 1] = d; +} + +static void PicoWriteM68k16_cell0(u32 a, u32 d) +{ + a = (a&3) | (cell_map(a >> 2) << 2); + *(u16 *)(Pico_mcd->word_ram1M[0] + a) = d; +} + +static void PicoWriteM68k16_cell1(u32 a, u32 d) +{ + a = (a&3) | (cell_map(a >> 2) << 2); + *(u16 *)(Pico_mcd->word_ram1M[1] + a) = d; +} +#endif + +// RAM cart (40000 - 7fffff, optional) +static u32 PicoReadM68k8_ramc(u32 a) +{ + u32 d = 0; + if (a == 0x400001) { + if (SRam.data != NULL) + d = 3; // 64k cart + return d; + } + + if ((a & 0xfe0000) == 0x600000) { + if (SRam.data != NULL) + d = SRam.data[((a >> 1) & 0xffff) + 0x2000]; + return d; + } + + if (a == 0x7fffff) + return Pico_mcd->m.bcram_reg; + + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return d; +} + +static u32 PicoReadM68k16_ramc(u32 a) +{ + elprintf(EL_ANOMALY, "ramcart r16: [%06x] @%06x", a, SekPcS68k); + return PicoReadM68k8_ramc(a + 1); +} + +static void PicoWriteM68k8_ramc(u32 a, u32 d) +{ + if ((a & 0xfe0000) == 0x600000) { + if (SRam.data != NULL && (Pico_mcd->m.bcram_reg & 1)) { + SRam.data[((a>>1) & 0xffff) + 0x2000] = d; + SRam.changed = 1; + } + return; + } + + if (a == 0x7fffff) { + Pico_mcd->m.bcram_reg = d; + return; + } + + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); +} + +static void PicoWriteM68k16_ramc(u32 a, u32 d) +{ + elprintf(EL_ANOMALY, "ramcart w16: [%06x] %04x @%06x", + a, d, SekPcS68k); + PicoWriteM68k8_ramc(a + 1, d); +} + +// IO/control/cd registers (a10000 - ...) +#ifndef _ASM_CD_MEMORY_C +u32 PicoRead8_mcd_io(u32 a) +{ + u32 d; + if ((a & 0xff00) == 0x2000) { // a12000 - a120ff + d = m68k_reg_read16(a); // TODO: m68k_reg_read8 + if (!(a & 1)) + d >>= 8; + d &= 0xff; + elprintf(EL_CDREGS, "m68k_regs r8: [%02x] %02x @%06x", + a & 0x3f, d, SekPc); + return d; + } + + // fallback to default MD handler + return PicoRead8_io(a); +} + +u32 PicoRead16_mcd_io(u32 a) +{ + u32 d; + if ((a & 0xff00) == 0x2000) { + d = m68k_reg_read16(a); + elprintf(EL_CDREGS, "m68k_regs r16: [%02x] %04x @%06x", + a & 0x3f, d, SekPc); + return d; + } + + return PicoRead16_io(a); +} + +void PicoWrite8_mcd_io(u32 a, u32 d) +{ + if ((a & 0xff00) == 0x2000) { // a12000 - a120ff + elprintf(EL_CDREGS, "m68k_regs w8: [%02x] %02x @%06x", + a & 0x3f, d, SekPc); + m68k_reg_write8(a, d); + return; + } + + PicoWrite8_io(a, d); +} + +void PicoWrite16_mcd_io(u32 a, u32 d) +{ + if ((a & 0xff00) == 0x2000) { // a12000 - a120ff + elprintf(EL_CDREGS, "m68k_regs w16: [%02x] %04x @%06x", + a & 0x3f, d, SekPc); + + m68k_reg_write8(a, d >> 8); + if ((a & 0x3e) != 0x0e) // special case + m68k_reg_write8(a + 1, d & 0xff); + return; + } + + PicoWrite16_io(a, d); +} +#endif + +// ----------------------------------------------------------------- +// Sub 68k +// ----------------------------------------------------------------- + +static u32 s68k_unmapped_read8(u32 a) +{ + elprintf(EL_UIO, "s68k unmapped r8 [%06x] @%06x", a, SekPc); + return 0; +} + +static u32 s68k_unmapped_read16(u32 a) +{ + elprintf(EL_UIO, "s68k unmapped r16 [%06x] @%06x", a, SekPc); + return 0; +} + +static void s68k_unmapped_write8(u32 a, u32 d) +{ + elprintf(EL_UIO, "s68k unmapped w8 [%06x] %02x @%06x", + a, d & 0xff, SekPc); +} + +static void s68k_unmapped_write16(u32 a, u32 d) +{ + elprintf(EL_UIO, "s68k unmapped w16 [%06x] %04x @%06x", + a, d & 0xffff, SekPc); +} + +// PRG RAM protected range (000000 - 01fdff)? +// XXX verify: ff00 or 1fe00 max? +static void PicoWriteS68k8_prgwp(u32 a, u32 d) +{ + if (a >= (Pico_mcd->s68k_regs[2] << 9)) + Pico_mcd->prg_ram[a ^ 1] = d; +} + +static void PicoWriteS68k16_prgwp(u32 a, u32 d) +{ + if (a >= (Pico_mcd->s68k_regs[2] << 9)) + *(u16 *)(Pico_mcd->prg_ram + a) = d; +} + +#ifndef _ASM_CD_MEMORY_C + +// decode (080000 - 0bffff, in 1M mode) +static u32 PicoReadS68k8_dec0(u32 a) +{ + u32 d = Pico_mcd->word_ram1M[0][((a >> 1) ^ 1) & 0x1ffff]; + if (a & 1) + d &= 0x0f; + else + d >>= 4; + return d; +} + +static u32 PicoReadS68k8_dec1(u32 a) +{ + u32 d = Pico_mcd->word_ram1M[1][((a >> 1) ^ 1) & 0x1ffff]; + if (a & 1) + d &= 0x0f; + else + d >>= 4; + return d; +} + +static u32 PicoReadS68k16_dec0(u32 a) +{ + u32 d = Pico_mcd->word_ram1M[0][((a >> 1) ^ 1) & 0x1ffff]; + d |= d << 4; + d &= ~0xf0; + return d; +} + +static u32 PicoReadS68k16_dec1(u32 a) +{ + u32 d = Pico_mcd->word_ram1M[1][((a >> 1) ^ 1) & 0x1ffff]; + d |= d << 4; + d &= ~0xf0; + return d; +} + +/* check: jaguar xj 220 (draws entire world using decode) */ +#define mk_decode_w8(bank) \ +static void PicoWriteS68k8_dec_m0b##bank(u32 a, u32 d) \ +{ \ + u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \ + \ + if (!(a & 1)) \ + *pd = (*pd & 0x0f) | (d << 4); \ + else \ + *pd = (*pd & 0xf0) | (d & 0x0f); \ +} \ + \ +static void PicoWriteS68k8_dec_m1b##bank(u32 a, u32 d) \ +{ \ + u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \ + u8 mask = (a & 1) ? 0x0f : 0xf0; \ + \ + if (!(*pd & mask) && (d & 0x0f)) /* underwrite */ \ + PicoWriteS68k8_dec_m0b##bank(a, d); \ +} \ + \ +static void PicoWriteS68k8_dec_m2b##bank(u32 a, u32 d) /* ...and m3? */ \ +{ \ + if (d & 0x0f) /* overwrite */ \ + PicoWriteS68k8_dec_m0b##bank(a, d); \ +} + +mk_decode_w8(0) +mk_decode_w8(1) + +#define mk_decode_w16(bank) \ +static void PicoWriteS68k16_dec_m0b##bank(u32 a, u32 d) \ +{ \ + u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \ + \ + d &= 0x0f0f; \ + *pd = d | (d >> 4); \ +} \ + \ +static void PicoWriteS68k16_dec_m1b##bank(u32 a, u32 d) \ +{ \ + u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \ + \ + d &= 0x0f0f; /* underwrite */ \ + if (!(*pd & 0xf0)) *pd |= d >> 4; \ + if (!(*pd & 0x0f)) *pd |= d; \ +} \ + \ +static void PicoWriteS68k16_dec_m2b##bank(u32 a, u32 d) \ +{ \ + u8 *pd = &Pico_mcd->word_ram1M[bank][((a >> 1) ^ 1) & 0x1ffff]; \ + \ + d &= 0x0f0f; /* overwrite */ \ + d |= d >> 4; \ + \ + if (!(d & 0xf0)) d |= *pd & 0xf0; \ + if (!(d & 0x0f)) d |= *pd & 0x0f; \ + *pd = d; \ +} + +mk_decode_w16(0) +mk_decode_w16(1) + +#endif + +// backup RAM (fe0000 - feffff) +static u32 PicoReadS68k8_bram(u32 a) +{ + return Pico_mcd->bram[(a>>1)&0x1fff]; +} + +static u32 PicoReadS68k16_bram(u32 a) +{ + u32 d; + elprintf(EL_ANOMALY, "FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k); + a = (a >> 1) & 0x1fff; + d = Pico_mcd->bram[a++]; + d|= Pico_mcd->bram[a++] << 8; // probably wrong, TODO: verify + return d; +} + +static void PicoWriteS68k8_bram(u32 a, u32 d) +{ + Pico_mcd->bram[(a >> 1) & 0x1fff] = d; + SRam.changed = 1; +} + +static void PicoWriteS68k16_bram(u32 a, u32 d) +{ + elprintf(EL_ANOMALY, "s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k); + a = (a >> 1) & 0x1fff; + Pico_mcd->bram[a++] = d; + Pico_mcd->bram[a++] = d >> 8; // TODO: verify.. + SRam.changed = 1; +} + +#ifndef _ASM_CD_MEMORY_C + +// PCM and registers (ff0000 - ffffff) +static u32 PicoReadS68k8_pr(u32 a) +{ + u32 d = 0; + + // regs + if ((a & 0xfe00) == 0x8000) { + a &= 0x1ff; + if (a >= 0x0e && a < 0x30) { + d = Pico_mcd->s68k_regs[a]; + s68k_poll_detect(a & ~1, d); + goto regs_done; + } + d = s68k_reg_read16(a & ~1); + if (!(a & 1)) + d >>= 8; + +regs_done: + d &= 0xff; + elprintf(EL_CDREGS, "s68k_regs r8: [%02x] %02x @%06x", + a, d, SekPcS68k); + return d; + } + + // PCM + // XXX: verify: probably odd addrs only? + if ((a & 0x8000) == 0x0000) { + a &= 0x7fff; + if (a >= 0x2000) + d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a >> 1) & 0xfff]; + else if (a >= 0x20) + d = pcd_pcm_read(a >> 1); + + return d; + } + + return s68k_unmapped_read8(a); +} + +static u32 PicoReadS68k16_pr(u32 a) +{ + u32 d = 0; + + // regs + if ((a & 0xfe00) == 0x8000) { + a &= 0x1fe; + d = s68k_reg_read16(a); + + elprintf(EL_CDREGS, "s68k_regs r16: [%02x] %04x @%06x", + a, d, SekPcS68k); + return d; + } + + // PCM + if ((a & 0x8000) == 0x0000) { + a &= 0x7fff; + if (a >= 0x2000) + d = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a >> 1) & 0xfff]; + else if (a >= 0x20) + d = pcd_pcm_read(a >> 1); + + return d; + } + + return s68k_unmapped_read16(a); +} + +static void PicoWriteS68k8_pr(u32 a, u32 d) +{ + // regs + if ((a & 0xfe00) == 0x8000) { + a &= 0x1ff; + elprintf(EL_CDREGS, "s68k_regs w8: [%02x] %02x @%06x", a, d, SekPcS68k); + if (0x59 <= a && a < 0x68) // word regs + s68k_reg_write16(a & ~1, (d << 8) | d); + else + s68k_reg_write8(a, d); + return; + } + + // PCM + if ((a & 0x8000) == 0x0000) { + a &= 0x7fff; + if (a >= 0x2000) + Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d; + else if (a < 0x12) + pcd_pcm_write(a>>1, d); + return; + } + + s68k_unmapped_write8(a, d); +} + +static void PicoWriteS68k16_pr(u32 a, u32 d) +{ + // regs + if ((a & 0xfe00) == 0x8000) { + a &= 0x1fe; + elprintf(EL_CDREGS, "s68k_regs w16: [%02x] %04x @%06x", a, d, SekPcS68k); + s68k_reg_write16(a, d); + return; + } + + // PCM + if ((a & 0x8000) == 0x0000) { + a &= 0x7fff; + if (a >= 0x2000) + Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank][(a>>1)&0xfff] = d; + else if (a < 0x12) + pcd_pcm_write(a>>1, d & 0xff); + return; + } + + s68k_unmapped_write16(a, d); +} + +#endif + +static const void *m68k_cell_read8[] = { PicoReadM68k8_cell0, PicoReadM68k8_cell1 }; +static const void *m68k_cell_read16[] = { PicoReadM68k16_cell0, PicoReadM68k16_cell1 }; +static const void *m68k_cell_write8[] = { PicoWriteM68k8_cell0, PicoWriteM68k8_cell1 }; +static const void *m68k_cell_write16[] = { PicoWriteM68k16_cell0, PicoWriteM68k16_cell1 }; + +static const void *s68k_dec_read8[] = { PicoReadS68k8_dec0, PicoReadS68k8_dec1 }; +static const void *s68k_dec_read16[] = { PicoReadS68k16_dec0, PicoReadS68k16_dec1 }; + +static const void *s68k_dec_write8[2][4] = { + { PicoWriteS68k8_dec_m0b0, PicoWriteS68k8_dec_m1b0, PicoWriteS68k8_dec_m2b0, PicoWriteS68k8_dec_m2b0 }, + { PicoWriteS68k8_dec_m0b1, PicoWriteS68k8_dec_m1b1, PicoWriteS68k8_dec_m2b1, PicoWriteS68k8_dec_m2b1 }, +}; + +static const void *s68k_dec_write16[2][4] = { + { PicoWriteS68k16_dec_m0b0, PicoWriteS68k16_dec_m1b0, PicoWriteS68k16_dec_m2b0, PicoWriteS68k16_dec_m2b0 }, + { PicoWriteS68k16_dec_m0b1, PicoWriteS68k16_dec_m1b1, PicoWriteS68k16_dec_m2b1, PicoWriteS68k16_dec_m2b1 }, +}; + +// ----------------------------------------------------------------- + +static void remap_prg_window(u32 r1, u32 r3) +{ + // PRG RAM + if (r1 & 2) { + void *bank = Pico_mcd->prg_ram_b[(r3 >> 6) & 3]; + cpu68k_map_all_ram(0x020000, 0x03ffff, bank, 0); + } + else { + m68k_map_unmap(0x020000, 0x03ffff); + } +} + +static void remap_word_ram(u32 r3) +{ + void *bank; + + // WORD RAM + if (!(r3 & 4)) { + // 2M mode. XXX: allowing access in all cases for simplicity + bank = Pico_mcd->word_ram2M; + cpu68k_map_all_ram(0x200000, 0x23ffff, bank, 0); + cpu68k_map_all_ram(0x080000, 0x0bffff, bank, 1); + // TODO: handle 0x0c0000 + } + else { + int b0 = r3 & 1; + int m = (r3 & 0x18) >> 3; + bank = Pico_mcd->word_ram1M[b0]; + cpu68k_map_all_ram(0x200000, 0x21ffff, bank, 0); + bank = Pico_mcd->word_ram1M[b0 ^ 1]; + cpu68k_map_all_ram(0x0c0000, 0x0effff, bank, 1); + // "cell arrange" on m68k + cpu68k_map_set(m68k_read8_map, 0x220000, 0x23ffff, m68k_cell_read8[b0], 1); + cpu68k_map_set(m68k_read16_map, 0x220000, 0x23ffff, m68k_cell_read16[b0], 1); + cpu68k_map_set(m68k_write8_map, 0x220000, 0x23ffff, m68k_cell_write8[b0], 1); + cpu68k_map_set(m68k_write16_map, 0x220000, 0x23ffff, m68k_cell_write16[b0], 1); + // "decode format" on s68k + cpu68k_map_set(s68k_read8_map, 0x080000, 0x0bffff, s68k_dec_read8[b0 ^ 1], 1); + cpu68k_map_set(s68k_read16_map, 0x080000, 0x0bffff, s68k_dec_read16[b0 ^ 1], 1); + cpu68k_map_set(s68k_write8_map, 0x080000, 0x0bffff, s68k_dec_write8[b0 ^ 1][m], 1); + cpu68k_map_set(s68k_write16_map, 0x080000, 0x0bffff, s68k_dec_write16[b0 ^ 1][m], 1); + } + +#ifdef EMU_F68K + // update fetchmap.. + int i; + if (!(r3 & 4)) + { + for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x240000; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram2M - 0x200000; + } + else + { + for (i = M68K_FETCHBANK1*2/16; (i<<(24-FAMEC_FETCHBITS)) < 0x220000; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram1M[r3 & 1] - 0x200000; + for (i = M68K_FETCHBANK1*0x0c/0x100; (i<<(24-FAMEC_FETCHBITS)) < 0x0e0000; i++) + PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram1M[(r3&1)^1] - 0x0c0000; + } +#endif +} + +void pcd_state_loaded_mem(void) +{ + u32 r3 = Pico_mcd->s68k_regs[3]; + + /* after load events */ + if (r3 & 4) // 1M mode? + wram_2M_to_1M(Pico_mcd->word_ram2M); + remap_word_ram(r3); + remap_prg_window(Pico_mcd->m.busreq, r3); + Pico_mcd->m.dmna_ret_2m &= 3; + + // restore hint vector + *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; +} + +#ifdef EMU_M68K +static void m68k_mem_setup_cd(void); +#endif + +PICO_INTERNAL void PicoMemSetupCD(void) +{ + // setup default main68k map + PicoMemSetup(); + + // main68k map (BIOS mapped by PicoMemSetup()): + // RAM cart + if (PicoOpt & POPT_EN_MCD_RAMCART) { + cpu68k_map_set(m68k_read8_map, 0x400000, 0x7fffff, PicoReadM68k8_ramc, 1); + cpu68k_map_set(m68k_read16_map, 0x400000, 0x7fffff, PicoReadM68k16_ramc, 1); + cpu68k_map_set(m68k_write8_map, 0x400000, 0x7fffff, PicoWriteM68k8_ramc, 1); + cpu68k_map_set(m68k_write16_map, 0x400000, 0x7fffff, PicoWriteM68k16_ramc, 1); + } + + // registers/IO: + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_mcd_io, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_mcd_io, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_mcd_io, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_mcd_io, 1); + + // sub68k map + cpu68k_map_set(s68k_read8_map, 0x000000, 0xffffff, s68k_unmapped_read8, 1); + cpu68k_map_set(s68k_read16_map, 0x000000, 0xffffff, s68k_unmapped_read16, 1); + cpu68k_map_set(s68k_write8_map, 0x000000, 0xffffff, s68k_unmapped_write8, 1); + cpu68k_map_set(s68k_write16_map, 0x000000, 0xffffff, s68k_unmapped_write16, 1); + + // PRG RAM + cpu68k_map_set(s68k_read8_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); + cpu68k_map_set(s68k_read16_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); + cpu68k_map_set(s68k_write8_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); + cpu68k_map_set(s68k_write16_map, 0x000000, 0x07ffff, Pico_mcd->prg_ram, 0); + cpu68k_map_set(s68k_write8_map, 0x000000, 0x01ffff, PicoWriteS68k8_prgwp, 1); + cpu68k_map_set(s68k_write16_map, 0x000000, 0x01ffff, PicoWriteS68k16_prgwp, 1); + + // BRAM + cpu68k_map_set(s68k_read8_map, 0xfe0000, 0xfeffff, PicoReadS68k8_bram, 1); + cpu68k_map_set(s68k_read16_map, 0xfe0000, 0xfeffff, PicoReadS68k16_bram, 1); + cpu68k_map_set(s68k_write8_map, 0xfe0000, 0xfeffff, PicoWriteS68k8_bram, 1); + cpu68k_map_set(s68k_write16_map, 0xfe0000, 0xfeffff, PicoWriteS68k16_bram, 1); + + // PCM, regs + cpu68k_map_set(s68k_read8_map, 0xff0000, 0xffffff, PicoReadS68k8_pr, 1); + cpu68k_map_set(s68k_read16_map, 0xff0000, 0xffffff, PicoReadS68k16_pr, 1); + cpu68k_map_set(s68k_write8_map, 0xff0000, 0xffffff, PicoWriteS68k8_pr, 1); + cpu68k_map_set(s68k_write16_map, 0xff0000, 0xffffff, PicoWriteS68k16_pr, 1); + + // RAMs + remap_word_ram(1); + +#ifdef EMU_C68K + // s68k + PicoCpuCS68k.read8 = (void *)s68k_read8_map; + PicoCpuCS68k.read16 = (void *)s68k_read16_map; + PicoCpuCS68k.read32 = (void *)s68k_read16_map; + PicoCpuCS68k.write8 = (void *)s68k_write8_map; + PicoCpuCS68k.write16 = (void *)s68k_write16_map; + PicoCpuCS68k.write32 = (void *)s68k_write16_map; + PicoCpuCS68k.checkpc = NULL; /* unused */ + PicoCpuCS68k.fetch8 = NULL; + PicoCpuCS68k.fetch16 = NULL; + PicoCpuCS68k.fetch32 = NULL; +#endif +#ifdef EMU_F68K + // s68k + PicoCpuFS68k.read_byte = s68k_read8; + PicoCpuFS68k.read_word = s68k_read16; + PicoCpuFS68k.read_long = s68k_read32; + PicoCpuFS68k.write_byte = s68k_write8; + PicoCpuFS68k.write_word = s68k_write16; + PicoCpuFS68k.write_long = s68k_write32; + + // setup FAME fetchmap + { + int i; + // M68k + // by default, point everything to fitst 64k of ROM (BIOS) + for (i = 0; i < M68K_FETCHBANK1; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom - (i<<(24-FAMEC_FETCHBITS)); + // now real ROM (BIOS) + for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom; + // .. and RAM + for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); + // S68k + // PRG RAM is default + for (i = 0; i < M68K_FETCHBANK1; i++) + PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->prg_ram - (i<<(24-FAMEC_FETCHBITS)); + // real PRG RAM + for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0x80000; i++) + PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->prg_ram; + // WORD RAM 2M area + for (i = M68K_FETCHBANK1*0x08/0x100; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < 0xc0000; i++) + PicoCpuFS68k.Fetch[i] = (unsigned long)Pico_mcd->word_ram2M - 0x80000; + // remap_word_ram() will setup word ram for both + } +#endif +#ifdef EMU_M68K + m68k_mem_setup_cd(); +#endif +} + + +#ifdef EMU_M68K +u32 m68k_read8(u32 a); +u32 m68k_read16(u32 a); +u32 m68k_read32(u32 a); +void m68k_write8(u32 a, u8 d); +void m68k_write16(u32 a, u16 d); +void m68k_write32(u32 a, u32 d); + +static unsigned int PicoReadCD8w (unsigned int a) { + return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read8(a) : m68k_read8(a); +} +static unsigned int PicoReadCD16w(unsigned int a) { + return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read16(a) : m68k_read16(a); +} +static unsigned int PicoReadCD32w(unsigned int a) { + return m68ki_cpu_p == &PicoCpuMS68k ? s68k_read32(a) : m68k_read32(a); +} +static void PicoWriteCD8w (unsigned int a, unsigned char d) { + if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write8(a, d); else m68k_write8(a, d); +} +static void PicoWriteCD16w(unsigned int a, unsigned short d) { + if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write16(a, d); else m68k_write16(a, d); +} +static void PicoWriteCD32w(unsigned int a, unsigned int d) { + if (m68ki_cpu_p == &PicoCpuMS68k) s68k_write32(a, d); else m68k_write32(a, d); +} + +extern unsigned int (*pm68k_read_memory_8) (unsigned int address); +extern unsigned int (*pm68k_read_memory_16)(unsigned int address); +extern unsigned int (*pm68k_read_memory_32)(unsigned int address); +extern void (*pm68k_write_memory_8) (unsigned int address, unsigned char value); +extern void (*pm68k_write_memory_16)(unsigned int address, unsigned short value); +extern void (*pm68k_write_memory_32)(unsigned int address, unsigned int value); + +static void m68k_mem_setup_cd(void) +{ + pm68k_read_memory_8 = PicoReadCD8w; + pm68k_read_memory_16 = PicoReadCD16w; + pm68k_read_memory_32 = PicoReadCD32w; + pm68k_write_memory_8 = PicoWriteCD8w; + pm68k_write_memory_16 = PicoWriteCD16w; + pm68k_write_memory_32 = PicoWriteCD32w; +} +#endif // EMU_M68K + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/misc.c b/waterbox/picodrive/pico/cd/misc.c new file mode 100644 index 0000000000..227b4b226b --- /dev/null +++ b/waterbox/picodrive/pico/cd/misc.c @@ -0,0 +1,66 @@ +/* + * PicoDrive + * (C) notaz, 2007 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" + +unsigned char formatted_bram[4*0x10] = +{ +#if 0 + 0x00, 0xd4, 0x63, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x03, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x53, 0xd2, 0xf5, 0x3a, 0x48, 0x50, 0x35, 0x0f, + 0x47, 0x14, 0xf5, 0x7e, 0x5c, 0xd4, 0xf3, 0x03, 0x00, 0x03, 0x12, 0x00, 0x0a, 0xff, 0xca, 0xa6, + 0xf5, 0x27, 0xed, 0x22, 0x47, 0xfa, 0x22, 0x96, 0x6c, 0xa5, 0x88, 0x14, 0x48, 0x48, 0x0a, 0xbb, +#endif + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x00, 0x7d, 0x00, 0x7d, 0x00, 0x7d, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x45, 0x47, 0x41, 0x5f, 0x43, 0x44, 0x5f, 0x52, 0x4f, 0x4d, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x52, 0x41, 0x4d, 0x5f, 0x43, 0x41, 0x52, 0x54, 0x52, 0x49, 0x44, 0x47, 0x45, 0x5f, 0x5f, 0x5f, + // SEGA_CD_ROM.....RAM_CARTRIDGE___ +}; + + +// offs | 2Mbit | 1Mbit | +// 0 | [ 2M | unused | +// 128K | bit ] | bank0 | +// 256K | unused | bank1 | + +#ifndef _ASM_MISC_C +PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m) +{ + unsigned short *m1M_b0, *m1M_b1; + unsigned int i, tmp, *m2M; + + m2M = (unsigned int *) (m + 0x40000); + m1M_b0 = (unsigned short *) m2M; + m1M_b1 = (unsigned short *) (m + 0x60000); + + for (i = 0x40000/4; i; i--) + { + tmp = *(--m2M); + *(--m1M_b0) = tmp; + *(--m1M_b1) = tmp >> 16; + } +} + +PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m) +{ + unsigned short *m1M_b0, *m1M_b1; + unsigned int i, tmp, *m2M; + + m2M = (unsigned int *) m; + m1M_b0 = (unsigned short *) (m + 0x20000); + m1M_b1 = (unsigned short *) (m + 0x40000); + + for (i = 0x40000/4; i; i--) + { + tmp = *m1M_b0++ | (*m1M_b1++ << 16); + *m2M++ = tmp; + } +} +#endif + diff --git a/waterbox/picodrive/pico/cd/pcm.c b/waterbox/picodrive/pico/cd/pcm.c new file mode 100644 index 0000000000..77bfa300b8 --- /dev/null +++ b/waterbox/picodrive/pico/cd/pcm.c @@ -0,0 +1,165 @@ +/* + * Emulation routines for the RF5C164 PCM chip + * (C) notaz, 2007, 2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" + +#define PCM_STEP_SHIFT 11 + +void pcd_pcm_write(unsigned int a, unsigned int d) +{ + unsigned int cycles = SekCyclesDoneS68k(); + if ((int)(cycles - Pico_mcd->pcm.update_cycles) >= 384) + pcd_pcm_sync(cycles); + + if (a < 7) + { + Pico_mcd->pcm.ch[Pico_mcd->pcm.cur_ch].regs[a] = d; + } + else if (a == 7) // control register + { + if (d & 0x40) + Pico_mcd->pcm.cur_ch = d & 7; + else + Pico_mcd->pcm.bank = d & 0xf; + Pico_mcd->pcm.control = d; + elprintf(EL_CD, "pcm control %02x", Pico_mcd->pcm.control); + } + else if (a == 8) + { + Pico_mcd->pcm.enabled = ~d; + } + Pico_mcd->pcm_regs_dirty = 1; +} + +unsigned int pcd_pcm_read(unsigned int a) +{ + unsigned int d, cycles = SekCyclesDoneS68k(); + if ((int)(cycles - Pico_mcd->pcm.update_cycles) >= 384) + pcd_pcm_sync(cycles); + + d = Pico_mcd->pcm.ch[(a >> 1) & 7].addr >> PCM_STEP_SHIFT; + if (a & 1) + d >>= 8; + + return d & 0xff; +} + +void pcd_pcm_sync(unsigned int to) +{ + unsigned int cycles = Pico_mcd->pcm.update_cycles; + int mul_l, mul_r, inc, smp; + struct pcm_chan *ch; + unsigned int addr; + int c, s, steps; + int enabled; + int *out; + + if ((int)(to - cycles) < 384) + return; + + steps = (to - cycles) / 384; + if (Pico_mcd->pcm_mixpos + steps > PCM_MIXBUF_LEN) + // shouldn't happen, but occasionally does + steps = PCM_MIXBUF_LEN - Pico_mcd->pcm_mixpos; + + // PCM disabled or all channels off + enabled = Pico_mcd->pcm.enabled; + if (!(Pico_mcd->pcm.control & 0x80)) + enabled = 0; + if (!enabled && !Pico_mcd->pcm_regs_dirty) + goto end; + + out = Pico_mcd->pcm_mixbuf + Pico_mcd->pcm_mixpos * 2; + Pico_mcd->pcm_mixbuf_dirty = 1; + Pico_mcd->pcm_regs_dirty = 0; + + for (c = 0; c < 8; c++) + { + ch = &Pico_mcd->pcm.ch[c]; + + if (!(enabled & (1 << c))) { + ch->addr = ch->regs[6] << (PCM_STEP_SHIFT + 8); + continue; // channel disabled + } + + addr = ch->addr; + inc = *(unsigned short *)&ch->regs[2]; + mul_l = ((int)ch->regs[0] * (ch->regs[1] & 0xf)) >> (5+1); + mul_r = ((int)ch->regs[0] * (ch->regs[1] >> 4)) >> (5+1); + + for (s = 0; s < steps; s++, addr = (addr + inc) & 0x7FFFFFF) + { + smp = Pico_mcd->pcm_ram[addr >> PCM_STEP_SHIFT]; + + // test for loop signal + if (smp == 0xff) + { + addr = *(unsigned short *)&ch->regs[4]; // loop_addr + smp = Pico_mcd->pcm_ram[addr]; + addr <<= PCM_STEP_SHIFT; + if (smp == 0xff) + break; + } + + if (smp & 0x80) + smp = -(smp & 0x7f); + + out[s*2 ] += smp * mul_l; // max 128 * 119 = 15232 + out[s*2+1] += smp * mul_r; + } + ch->addr = addr; + } + +end: + Pico_mcd->pcm.update_cycles = cycles + steps * 384; + Pico_mcd->pcm_mixpos += steps; +} + +void pcd_pcm_update(int *buf32, int length, int stereo) +{ + int step, *pcm; + int p = 0; + + pcd_pcm_sync(SekCyclesDoneS68k()); + + if (!Pico_mcd->pcm_mixbuf_dirty || !(PicoOpt & POPT_EN_MCD_PCM)) + goto out; + + step = (Pico_mcd->pcm_mixpos << 16) / length; + pcm = Pico_mcd->pcm_mixbuf; + + if (stereo) { + while (length-- > 0) { + *buf32++ += pcm[0]; + *buf32++ += pcm[1]; + + p += step; + pcm += (p >> 16) * 2; + p &= 0xffff; + } + } + else { + while (length-- > 0) { + // mostly unused + *buf32++ += pcm[0]; + + p += step; + pcm += (p >> 16) * 2; + p &= 0xffff; + } + } + + memset(Pico_mcd->pcm_mixbuf, 0, + Pico_mcd->pcm_mixpos * 2 * sizeof(Pico_mcd->pcm_mixbuf[0])); + +out: + Pico_mcd->pcm_mixbuf_dirty = 0; + Pico_mcd->pcm_mixpos = 0; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/cd/sek.c b/waterbox/picodrive/pico/cd/sek.c new file mode 100644 index 0000000000..d4914901c0 --- /dev/null +++ b/waterbox/picodrive/pico/cd/sek.c @@ -0,0 +1,205 @@ +/* + * PicoDrive + * (C) notaz, 2007 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "../pico_int.h" + + +unsigned int SekCycleCntS68k; +unsigned int SekCycleAimS68k; + + +/* context */ +// Cyclone 68000 +#ifdef EMU_C68K +struct Cyclone PicoCpuCS68k; +#endif +// MUSASHI 68000 +#ifdef EMU_M68K +m68ki_cpu_core PicoCpuMS68k; +#endif +// FAME 68000 +#ifdef EMU_F68K +M68K_CONTEXT PicoCpuFS68k; +#endif + + +static int new_irq_level(int level) +{ + int level_new = 0, irqs; + Pico_mcd->m.s68k_pend_ints &= ~(1 << level); + irqs = Pico_mcd->m.s68k_pend_ints; + irqs &= Pico_mcd->s68k_regs[0x33]; + while ((irqs >>= 1)) level_new++; + + return level_new; +} + +#ifdef EMU_C68K +// interrupt acknowledgement +static int SekIntAckS68k(int level) +{ + int level_new = new_irq_level(level); + + elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); + PicoCpuCS68k.irq = level_new; + return CYCLONE_INT_ACK_AUTOVECTOR; +} + +static void SekResetAckS68k(void) +{ + elprintf(EL_ANOMALY, "s68k: Reset encountered @ %06x", SekPcS68k); +} + +static int SekUnrecognizedOpcodeS68k(void) +{ + elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", SekPcS68k); + //exit(1); + return 0; +} +#endif + +#ifdef EMU_M68K +static int SekIntAckMS68k(int level) +{ +#ifndef EMU_CORE_DEBUG + int level_new = new_irq_level(level); + elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); + CPU_INT_LEVEL = level_new << 8; +#else + CPU_INT_LEVEL = 0; +#endif + return M68K_INT_ACK_AUTOVECTOR; +} +#endif + +#ifdef EMU_F68K +static void SekIntAckFS68k(unsigned level) +{ + int level_new = new_irq_level(level); + elprintf(EL_INTS, "s68kACK %i -> %i", level, level_new); +#ifndef EMU_CORE_DEBUG + PicoCpuFS68k.interrupts[0] = level_new; +#else + { + extern int dbg_irq_level_sub; + dbg_irq_level_sub = level_new; + PicoCpuFS68k.interrupts[0] = 0; + } +#endif +} +#endif + + +PICO_INTERNAL void SekInitS68k(void) +{ +#ifdef EMU_C68K +// CycloneInit(); + memset(&PicoCpuCS68k,0,sizeof(PicoCpuCS68k)); + PicoCpuCS68k.IrqCallback=SekIntAckS68k; + PicoCpuCS68k.ResetCallback=SekResetAckS68k; + PicoCpuCS68k.UnrecognizedCallback=SekUnrecognizedOpcodeS68k; +#endif +#ifdef EMU_M68K + { + // Musashi is not very context friendly.. + void *oldcontext = m68ki_cpu_p; + m68k_set_context(&PicoCpuMS68k); + m68k_set_cpu_type(M68K_CPU_TYPE_68000); + m68k_init(); + m68k_set_int_ack_callback(SekIntAckMS68k); +// m68k_pulse_reset(); // not yet, memmap is not set up + m68k_set_context(oldcontext); + } +#endif +#ifdef EMU_F68K + { + void *oldcontext = g_m68kcontext; + g_m68kcontext = &PicoCpuFS68k; + memset(&PicoCpuFS68k, 0, sizeof(PicoCpuFS68k)); + fm68k_init(); + PicoCpuFS68k.iack_handler = SekIntAckFS68k; + PicoCpuFS68k.sr = 0x2704; // Z flag + g_m68kcontext = oldcontext; + } +#endif +} + +// Reset the 68000: +PICO_INTERNAL int SekResetS68k(void) +{ + if (Pico.rom==NULL) return 1; + +#ifdef EMU_C68K + CycloneReset(&PicoCpuCS68k); +#endif +#ifdef EMU_M68K + { + void *oldcontext = m68ki_cpu_p; + + m68k_set_context(&PicoCpuMS68k); + m68ki_cpu.sp[0]=0; + m68k_set_irq(0); + m68k_pulse_reset(); + m68k_set_context(oldcontext); + } +#endif +#ifdef EMU_F68K + { + void *oldcontext = g_m68kcontext; + g_m68kcontext = &PicoCpuFS68k; + fm68k_reset(); + g_m68kcontext = oldcontext; + } +#endif + + return 0; +} + +PICO_INTERNAL int SekInterruptS68k(int irq) +{ + int irqs, real_irq = 1; + Pico_mcd->m.s68k_pend_ints |= 1 << irq; + irqs = Pico_mcd->m.s68k_pend_ints >> 1; + while ((irqs >>= 1)) real_irq++; + +#ifdef EMU_CORE_DEBUG + { + extern int dbg_irq_level_sub; + dbg_irq_level_sub=real_irq; + return 0; + } +#endif +#ifdef EMU_C68K + PicoCpuCS68k.irq=real_irq; +#endif +#ifdef EMU_M68K + void *oldcontext = m68ki_cpu_p; + m68k_set_context(&PicoCpuMS68k); + m68k_set_irq(real_irq); + m68k_set_context(oldcontext); +#endif +#ifdef EMU_F68K + PicoCpuFS68k.interrupts[0]=real_irq; +#endif + return 0; +} + +void SekInterruptClearS68k(int irq) +{ + int level_new = new_irq_level(irq); + +#ifdef EMU_C68K + PicoCpuCS68k.irq = level_new; +#endif +#ifdef EMU_M68K + CPU_INT_LEVEL = level_new << 8; +#endif +#ifdef EMU_F68K + PicoCpuFS68k.interrupts[0] = level_new; +#endif +} diff --git a/waterbox/picodrive/pico/draw.c b/waterbox/picodrive/pico/draw.c new file mode 100644 index 0000000000..a03d8873a8 --- /dev/null +++ b/waterbox/picodrive/pico/draw.c @@ -0,0 +1,1602 @@ +/* + * line renderer + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +/* + * The renderer has 4 modes now: + * - normal + * - shadow/hilight (s/h) + * - "sonic mode" for midline palette changes (8bit mode only) + * - accurate sprites (AS) [+ s/h] + * + * AS and s/h both use upper bits for both priority and shadow/hilight flags. + * "sonic mode" is autodetected, shadow/hilight is enabled by emulated game. + * AS is enabled by user and takes priority over "sonic mode". + * + * since renderer always draws line in 8bit mode, there are 2 spare bits: + * b \ mode: s/h as sonic + * 00 normal - pal index + * 01 shadow - pal index + * 10 hilight+op spr spr pal index + * 11 shadow +op spr - pal index + * + * not handled properly: + * - hilight op on shadow tile + * - AS + s/h (s/h sprite flag interferes with and cleared by AS code) + */ + +#include "pico_int.h" + +int (*PicoScanBegin)(unsigned int num) = NULL; +int (*PicoScanEnd) (unsigned int num) = NULL; + +static unsigned char DefHighCol[8+320+8]; +unsigned char *HighCol = DefHighCol; +static unsigned char *HighColBase = DefHighCol; +static int HighColIncrement; + +static unsigned int DefOutBuff[320*2/2]; +void *DrawLineDest = DefOutBuff; // pointer to dest buffer where to draw this line to +void *DrawLineDestBase = DefOutBuff; +int DrawLineDestIncrement; + +static int HighCacheA[41+1]; // caches for high layers +static int HighCacheB[41+1]; +int HighPreSpr[80*2+1]; // slightly preprocessed sprites + +#define SPRL_HAVE_HI 0x80 // have hi priority sprites +#define SPRL_HAVE_LO 0x40 // *lo* +#define SPRL_MAY_HAVE_OP 0x20 // may have operator sprites on the line +#define SPRL_LO_ABOVE_HI 0x10 // low priority sprites may be on top of hi +unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; // sprite_count, ^flags, tile_count, [spritep]... + +int rendstatus, rendstatus_old; +int rendlines; +int DrawScanline; +int PicoDrawMask = -1; + +static int skip_next_line=0; + +//unsigned short ppt[] = { 0x0f11, 0x0ff1, 0x01f1, 0x011f, 0x01ff, 0x0f1f, 0x0f0e, 0x0e7c }; + +struct TileStrip +{ + int nametab; // Position in VRAM of name table (for this tile line) + int line; // Line number in pixels 0x000-0x3ff within the virtual tilemap + int hscroll; // Horizontal scroll value in pixels for the line + int xmask; // X-Mask (0x1f - 0x7f) for horizontal wraparound in the tilemap + int *hc; // cache for high tile codes and their positions + int cells; // cells (tiles) to draw (32 col mode doesn't need to update whole 320) +}; + +// stuff available in asm: +#ifdef _ASM_DRAW_C +void DrawWindow(int tstart, int tend, int prio, int sh); +void DrawAllSprites(unsigned char *sprited, int prio, int sh); +void DrawTilesFromCache(int *hc, int sh, int rlim); +void DrawSpritesSHi(unsigned char *sprited); +void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells); +void FinalizeLineBGR444(int sh, int line); +void *blockcpy(void *dst, const void *src, size_t n); +void blockcpy_or(void *dst, void *src, size_t n, int pat); +#else +// utility +void blockcpy_or(void *dst, void *src, size_t n, int pat) +{ + unsigned char *pd = dst, *ps = src; + for (; n; n--) + *pd++ = (unsigned char) (*ps++ | pat); +} +#define blockcpy memcpy +#endif + + +#define TileNormMaker(funcname,pix_func) \ +static int funcname(int sx,int addr,int pal) \ +{ \ + unsigned char *pd = HighCol+sx; \ + unsigned int pack=0; unsigned int t=0; \ + \ + pack=*(unsigned int *)(Pico.vram+addr); /* Get 8 pixels */ \ + if (pack) \ + { \ + t=(pack&0x0000f000)>>12; pix_func(0); \ + t=(pack&0x00000f00)>> 8; pix_func(1); \ + t=(pack&0x000000f0)>> 4; pix_func(2); \ + t=(pack&0x0000000f) ; pix_func(3); \ + t=(pack&0xf0000000)>>28; pix_func(4); \ + t=(pack&0x0f000000)>>24; pix_func(5); \ + t=(pack&0x00f00000)>>20; pix_func(6); \ + t=(pack&0x000f0000)>>16; pix_func(7); \ + return 0; \ + } \ + \ + return 1; /* Tile blank */ \ +} + + +#define TileFlipMaker(funcname,pix_func) \ +static int funcname(int sx,int addr,int pal) \ +{ \ + unsigned char *pd = HighCol+sx; \ + unsigned int pack=0; unsigned int t=0; \ + \ + pack=*(unsigned int *)(Pico.vram+addr); /* Get 8 pixels */ \ + if (pack) \ + { \ + t=(pack&0x000f0000)>>16; pix_func(0); \ + t=(pack&0x00f00000)>>20; pix_func(1); \ + t=(pack&0x0f000000)>>24; pix_func(2); \ + t=(pack&0xf0000000)>>28; pix_func(3); \ + t=(pack&0x0000000f) ; pix_func(4); \ + t=(pack&0x000000f0)>> 4; pix_func(5); \ + t=(pack&0x00000f00)>> 8; pix_func(6); \ + t=(pack&0x0000f000)>>12; pix_func(7); \ + return 0; \ + } \ + \ + return 1; /* Tile blank */ \ +} + + +#ifdef _ASM_DRAW_C_AMIPS +int TileNorm(int sx,int addr,int pal); +int TileFlip(int sx,int addr,int pal); +#else + +#define pix_just_write(x) \ + if (t) pd[x]=pal|t + +TileNormMaker(TileNorm,pix_just_write) +TileFlipMaker(TileFlip,pix_just_write) + +#endif + +#ifndef _ASM_DRAW_C + +// draw a sprite pixel, process operator colors +#define pix_sh(x) \ + if (!t); \ + else if (t>=0xe) pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \ + else pd[x]=pal|t + +TileNormMaker(TileNormSH, pix_sh) +TileFlipMaker(TileFlipSH, pix_sh) + +// draw a sprite pixel, mark operator colors +#define pix_sh_markop(x) \ + if (!t); \ + else if (t>=0xe) pd[x]|=0x80; \ + else pd[x]=pal|t + +TileNormMaker(TileNormSH_markop, pix_sh_markop) +TileFlipMaker(TileFlipSH_markop, pix_sh_markop) + +// process operator pixels only, apply only on low pri tiles and other op pixels +#define pix_sh_onlyop(x) \ + if (t>=0xe && (pd[x]&0xc0)) \ + pd[x]=(pd[x]&0x3f)|(t<<6); /* c0 shadow, 80 hilight */ \ + +TileNormMaker(TileNormSH_onlyop_lp, pix_sh_onlyop) +TileFlipMaker(TileFlipSH_onlyop_lp, pix_sh_onlyop) + +#endif + +// draw a sprite pixel (AS) +#define pix_as(x) \ + if (t && !(pd[x]&0x80)) pd[x]=pal|t + +TileNormMaker(TileNormAS, pix_as) +TileFlipMaker(TileFlipAS, pix_as) + +// draw a sprite pixel, skip operator colors (AS) +#define pix_sh_as_noop(x) \ + if (t && t < 0xe && !(pd[x]&0x80)) pd[x]=pal|t + +TileNormMaker(TileNormAS_noop, pix_sh_as_noop) +TileFlipMaker(TileFlipAS_noop, pix_sh_as_noop) + +// mark pixel as sprite pixel (AS) +#define pix_sh_as_onlymark(x) \ + if (t) pd[x]|=0x80 + +TileNormMaker(TileNormAS_onlymark, pix_sh_as_onlymark) +TileFlipMaker(TileFlipAS_onlymark, pix_sh_as_onlymark) + + +// -------------------------------------------- + +#ifndef _ASM_DRAW_C +static void DrawStrip(struct TileStrip *ts, int plane_sh, int cellskip) +{ + int tilex,dx,ty,code=0,addr=0,cells; + int oldcode=-1,blank=-1; // The tile we know is blank + int pal=0,sh; + + // Draw tiles across screen: + sh=(plane_sh<<5)&0x40; + tilex=((-ts->hscroll)>>3)+cellskip; + ty=(ts->line&7)<<1; // Y-Offset into tile + dx=((ts->hscroll-1)&7)+1; + cells = ts->cells - cellskip; + if(dx != 8) cells++; // have hscroll, need to draw 1 cell more + dx+=cellskip<<3; + + for (; cells > 0; dx+=8,tilex++,cells--) + { + int zero=0; + + code=Pico.vram[ts->nametab+(tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + int cval = code | (dx<<16) | (ty<<25); + if(code&0x1000) cval^=7<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<4; + addr+=ty; + if (code&0x1000) addr^=0xe; // Y-flip + + pal=((code>>9)&0x30)|sh; + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; + // if oldcode wasn't changed, it means all layer is hi priority + if (oldcode == -1) rendstatus |= PDRAW_PLANE_HI_PRIO; +} + +// this is messy +void DrawStripVSRam(struct TileStrip *ts, int plane_sh, int cellskip) +{ + int tilex,dx,code=0,addr=0,cell=0; + int oldcode=-1,blank=-1; // The tile we know is blank + int pal=0,scan=DrawScanline; + + // Draw tiles across screen: + tilex=(-ts->hscroll)>>3; + dx=((ts->hscroll-1)&7)+1; + if(dx != 8) cell--; // have hscroll, start with negative cell + cell+=cellskip; + tilex+=cellskip; + dx+=cellskip<<3; + + for (; cell < ts->cells; dx+=8,tilex++,cell++) + { + int zero=0,nametabadd,ty; + + //if((cell&1)==0) + { + int line,vscroll; + vscroll=Pico.vsram[(plane_sh&1)+(cell&~1)]; + + // Find the line in the name table + line=(vscroll+scan)&ts->line&0xffff; // ts->line is really ymask .. + nametabadd=(line>>3)<<(ts->line>>24); // .. and shift[width] + ty=(line&7)<<1; // Y-Offset into tile + } + + code=Pico.vram[ts->nametab+nametabadd+(tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + int cval = code | (dx<<16) | (ty<<25); + if(code&0x1000) cval^=7<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<4; + if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip + + pal=((code>>9)&0x30)|((plane_sh<<5)&0x40); + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; + if (oldcode == -1) rendstatus |= PDRAW_PLANE_HI_PRIO; +} +#endif + +#ifndef _ASM_DRAW_C +static +#endif +void DrawStripInterlace(struct TileStrip *ts) +{ + int tilex=0,dx=0,ty=0,code=0,addr=0,cells; + int oldcode=-1,blank=-1; // The tile we know is blank + int pal=0; + + // Draw tiles across screen: + tilex=(-ts->hscroll)>>3; + ty=(ts->line&15)<<1; // Y-Offset into tile + dx=((ts->hscroll-1)&7)+1; + cells = ts->cells; + if(dx != 8) cells++; // have hscroll, need to draw 1 cell more + + for (; cells; dx+=8,tilex++,cells--) + { + int zero=0; + + code=Pico.vram[ts->nametab+(tilex&ts->xmask)]; + if (code==blank) continue; + if (code>>15) { // high priority tile + int cval = (code&0xfc00) | (dx<<16) | (ty<<25); + cval|=(code&0x3ff)<<1; + if(code&0x1000) cval^=0xf<<26; + *ts->hc++ = cval; // cache it + continue; + } + + if (code!=oldcode) { + oldcode = code; + // Get tile address/2: + addr=(code&0x7ff)<<5; + if (code&0x1000) addr+=30-ty; else addr+=ty; // Y-flip + +// pal=Pico.cram+((code>>9)&0x30); + pal=((code>>9)&0x30); + } + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + + // terminate the cache list + *ts->hc = 0; +} + +// -------------------------------------------- + +#ifndef _ASM_DRAW_C +static void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells) +{ + struct PicoVideo *pvid=&Pico.video; + const char shift[4]={5,6,5,7}; // 32,64 or 128 sized tilemaps (2 is invalid) + struct TileStrip ts; + int width, height, ymask; + int vscroll, htab; + + ts.hc=hcache; + ts.cells=maxcells; + + // Work out the TileStrip to draw + + // Work out the name table size: 32 64 or 128 tiles (0-3) + width=pvid->reg[16]; + height=(width>>4)&3; width&=3; + + ts.xmask=(1<1) ymask =0x0ff; + + // Find name table: + if (plane_sh&1) ts.nametab=(pvid->reg[4]&0x07)<<12; // B + else ts.nametab=(pvid->reg[2]&0x38)<< 9; // A + + htab=pvid->reg[13]<<9; // Horizontal scroll table address + if ( pvid->reg[11]&2) htab+=DrawScanline<<1; // Offset by line + if ((pvid->reg[11]&1)==0) htab&=~0xf; // Offset by tile + htab+=plane_sh&1; // A or B + + // Get horizontal scroll value, will be masked later + ts.hscroll=Pico.vram[htab&0x7fff]; + + if((pvid->reg[12]&6) == 6) { + // interlace mode 2 + vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value + + // Find the line in the name table + ts.line=(vscroll+(DrawScanline<<1))&((ymask<<1)|1); + ts.nametab+=(ts.line>>4)<reg[11]&4) { + // shit, we have 2-cell column based vscroll + // luckily this doesn't happen too often + ts.line=ymask|(shift[width]<<24); // save some stuff instead of line + DrawStripVSRam(&ts, plane_sh, cellskip); + } else { + vscroll=Pico.vsram[plane_sh&1]; // Get vertical scroll value + + // Find the line in the name table + ts.line=(vscroll+DrawScanline)&ymask; + ts.nametab+=(ts.line>>3)<reg[12]&1) + { + nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode + nametab+=(DrawScanline>>3)<<6; + } + else + { + nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode + nametab+=(DrawScanline>>3)<<5; + } + + tilex=tstart<<1; + + if (!(rendstatus & PDRAW_WND_DIFF_PRIO)) { + // check the first tile code + code=Pico.vram[nametab+tilex]; + // if the whole window uses same priority (what is often the case), we may be able to skip this field + if ((code>>15) != prio) return; + } + + tend<<=1; + ty=(DrawScanline&7)<<1; // Y-Offset into tile + + // Draw tiles across screen: + if (!sh) + { + for (; tilex < tend; tilex++) + { + int addr=0,zero=0; + int pal; + + code=Pico.vram[nametab+tilex]; + if (code==blank) continue; + if ((code>>15) != prio) { + rendstatus |= PDRAW_WND_DIFF_PRIO; + continue; + } + + pal=((code>>9)&0x30); + + // Get tile address/2: + addr=(code&0x7ff)<<4; + if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip + + if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal); + else zero=TileNorm(8+(tilex<<3),addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + } + else + { + for (; tilex < tend; tilex++) + { + int addr=0,zero=0; + int pal; + + code=Pico.vram[nametab+tilex]; + if(code==blank) continue; + if((code>>15) != prio) { + rendstatus |= PDRAW_WND_DIFF_PRIO; + continue; + } + + pal=((code>>9)&0x30); + + if (prio) { + int *zb = (int *)(HighCol+8+(tilex<<3)); + *zb++ &= 0xbfbfbfbf; + *zb &= 0xbfbfbfbf; + } else { + pal |= 0x40; + } + + // Get tile address/2: + addr=(code&0x7ff)<<4; + if (code&0x1000) addr+=14-ty; else addr+=ty; // Y-flip + + if (code&0x0800) zero=TileFlip(8+(tilex<<3),addr,pal); + else zero=TileNorm(8+(tilex<<3),addr,pal); + + if (zero) blank=code; // We know this tile is blank now + } + } +} + +// -------------------------------------------- + +static void DrawTilesFromCacheShPrep(void) +{ + // as some layer has covered whole line with hi priority tiles, + // we can process whole line and then act as if sh/hi mode was off, + // but leave lo pri op sprite markers alone + int c = 320/4, *zb = (int *)(HighCol+8); + rendstatus |= PDRAW_SHHI_DONE; + while (c--) + { + *zb++ &= 0xbfbfbfbf; + } +} + +static void DrawTilesFromCache(int *hc, int sh, int rlim) +{ + int code, addr, dx; + int pal; + + // *ts->hc++ = code | (dx<<16) | (ty<<25); // cache it + + if (sh && (rendstatus & (PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO))) + { + if (!(rendstatus & PDRAW_SHHI_DONE)) + DrawTilesFromCacheShPrep(); + sh = 0; + } + + if (!sh) + { + short blank=-1; // The tile we know is blank + while ((code=*hc++)) { + int zero; + if((short)code == blank) continue; + // Get tile address/2: + addr=(code&0x7ff)<<4; + addr+=(unsigned int)code>>25; // y offset into tile + dx=(code>>16)&0x1ff; + + pal=((code>>9)&0x30); + if (rlim-dx < 0) goto last_cut_tile; + + if (code&0x0800) zero=TileFlip(dx,addr,pal); + else zero=TileNorm(dx,addr,pal); + + if (zero) blank=(short)code; + } + } + else + { + while ((code=*hc++)) { + unsigned char *zb; + // Get tile address/2: + addr=(code&0x7ff)<<4; + addr+=(unsigned int)code>>25; // y offset into tile + dx=(code>>16)&0x1ff; + zb = HighCol+dx; + *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; + *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; *zb++ &= 0xbf; + + pal=((code>>9)&0x30); + if (rlim-dx < 0) goto last_cut_tile; + + if (code&0x0800) TileFlip(dx,addr,pal); + else TileNorm(dx,addr,pal); + } + } + return; + +last_cut_tile: + { + unsigned int t, pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + unsigned char *pd = HighCol+dx; + if (!pack) return; + if (code&0x0800) + { + switch (rlim-dx+8) + { + case 7: t=pack&0x00000f00; if (t) pd[6]=(unsigned char)(pal|(t>> 8)); // "break" is left out intentionally + case 6: t=pack&0x000000f0; if (t) pd[5]=(unsigned char)(pal|(t>> 4)); + case 5: t=pack&0x0000000f; if (t) pd[4]=(unsigned char)(pal|(t )); + case 4: t=pack&0xf0000000; if (t) pd[3]=(unsigned char)(pal|(t>>28)); + case 3: t=pack&0x0f000000; if (t) pd[2]=(unsigned char)(pal|(t>>24)); + case 2: t=pack&0x00f00000; if (t) pd[1]=(unsigned char)(pal|(t>>20)); + case 1: t=pack&0x000f0000; if (t) pd[0]=(unsigned char)(pal|(t>>16)); + default: break; + } + } + else + { + switch (rlim-dx+8) + { + case 7: t=pack&0x00f00000; if (t) pd[6]=(unsigned char)(pal|(t>>20)); + case 6: t=pack&0x0f000000; if (t) pd[5]=(unsigned char)(pal|(t>>24)); + case 5: t=pack&0xf0000000; if (t) pd[4]=(unsigned char)(pal|(t>>28)); + case 4: t=pack&0x0000000f; if (t) pd[3]=(unsigned char)(pal|(t )); + case 3: t=pack&0x000000f0; if (t) pd[2]=(unsigned char)(pal|(t>> 4)); + case 2: t=pack&0x00000f00; if (t) pd[1]=(unsigned char)(pal|(t>> 8)); + case 1: t=pack&0x0000f000; if (t) pd[0]=(unsigned char)(pal|(t>>12)); + default: break; + } + } + } +} + +// -------------------------------------------- + +// Index + 0 : hhhhvvvv ab--hhvv yyyyyyyy yyyyyyyy // a: offscreen h, b: offs. v, h: horiz. size +// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + +static void DrawSprite(int *sprite, int sh) +{ + int width=0,height=0; + int row=0,code=0; + int pal; + int tile=0,delta=0; + int sx, sy; + int (*fTileFunc)(int sx,int addr,int pal); + + // parse the sprite data + sy=sprite[0]; + code=sprite[1]; + sx=code>>16; // X + width=sy>>28; + height=(sy>>24)&7; // Width and height in tiles + sy=(sy<<16)>>16; // Y + + row=DrawScanline-sy; // Row of the sprite we are on + + if (code&0x1000) row=(height<<3)-1-row; // Flip Y + + tile=code + (row>>3); // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address + delta<<=4; // Delta of address + + pal=(code>>9)&0x30; + pal|=sh<<6; + + if (sh && (code&0x6000) == 0x6000) { + if(code&0x0800) fTileFunc=TileFlipSH_markop; + else fTileFunc=TileNormSH_markop; + } else { + if(code&0x0800) fTileFunc=TileFlip; + else fTileFunc=TileNorm; + } + + for (; width; width--,sx+=8,tile+=delta) + { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal); + } +} +#endif + +static void DrawSpriteInterlace(unsigned int *sprite) +{ + int width=0,height=0; + int row=0,code=0; + int pal; + int tile=0,delta=0; + int sx, sy; + + // parse the sprite data + sy=sprite[0]; + height=sy>>24; + sy=(sy&0x3ff)-0x100; // Y + width=(height>>2)&3; height&=3; + width++; height++; // Width and height in tiles + + row=(DrawScanline<<1)-sy; // Row of the sprite we are on + + code=sprite[1]; + sx=((code>>16)&0x1ff)-0x78; // X + + if (code&0x1000) row^=(16<>4; // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile<<=5; tile+=(row&15)<<1; // Tile address + + delta<<=5; // Delta of address + pal=((code>>9)&0x30); // Get palette pointer + + for (; width; width--,sx+=8,tile+=delta) + { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + if (code&0x0800) TileFlip(sx,tile,pal); + else TileNorm(sx,tile,pal); + } +} + + +static void DrawAllSpritesInterlace(int pri, int sh) +{ + struct PicoVideo *pvid=&Pico.video; + int i,u,table,link=0,sline=DrawScanline<<1; + unsigned int *sprites[80]; // Sprite index + + table=pvid->reg[5]&0x7f; + if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + table<<=8; // Get sprite table address/2 + + for (i=u=0; u < 80 && i < 21; u++) + { + unsigned int *sprite; + int code, sx, sy, height; + + sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + + // get sprite info + code = sprite[0]; + sx = sprite[1]; + if(((sx>>15)&1) != pri) goto nextsprite; // wrong priority sprite + + // check if it is on this line + sy = (code&0x3ff)-0x100; + height = (((code>>24)&3)+1)<<4; + if(sline < sy || sline >= sy+height) goto nextsprite; // no + + // check if sprite is not hidden offscreen + sx = (sx>>16)&0x1ff; + sx -= 0x78; // Get X coordinate + 8 + if(sx <= -8*3 || sx >= 328) goto nextsprite; + + // sprite is good, save it's pointer + sprites[i++]=sprite; + + nextsprite: + // Find next sprite + link=(code>>16)&0x7f; + if(!link) break; // End of sprites + } + + // Go through sprites backwards: + for (i-- ;i>=0; i--) + DrawSpriteInterlace(sprites[i]); +} + + +#ifndef _ASM_DRAW_C +/* + * s/h drawing: lo_layers|40, lo_sprites|40 && mark_op, + * hi_layers&=~40, hi_sprites + * + * Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size + * Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + */ +static void DrawSpritesSHi(unsigned char *sprited) +{ + int (*fTileFunc)(int sx,int addr,int pal); + unsigned char *p; + int cnt; + + cnt = sprited[0] & 0x7f; + if (cnt == 0) return; + + p = &sprited[3]; + + // Go through sprites backwards: + for (cnt--; cnt >= 0; cnt--) + { + int *sprite, code, pal, tile, sx, sy; + int offs, delta, width, height, row; + + offs = (p[cnt] & 0x7f) * 2; + sprite = HighPreSpr + offs; + code = sprite[1]; + pal = (code>>9)&0x30; + + if (pal == 0x30) + { + if (code & 0x8000) // hi priority + { + if (code&0x800) fTileFunc=TileFlipSH; + else fTileFunc=TileNormSH; + } else { + if (code&0x800) fTileFunc=TileFlipSH_onlyop_lp; + else fTileFunc=TileNormSH_onlyop_lp; + } + } else { + if (!(code & 0x8000)) continue; // non-operator low sprite, already drawn + if (code&0x800) fTileFunc=TileFlip; + else fTileFunc=TileNorm; + } + + // parse remaining sprite data + sy=sprite[0]; + sx=code>>16; // X + width=sy>>28; + height=(sy>>24)&7; // Width and height in tiles + sy=(sy<<16)>>16; // Y + + row=DrawScanline-sy; // Row of the sprite we are on + + if (code&0x1000) row=(height<<3)-1-row; // Flip Y + + tile=code + (row>>3); // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address + delta<<=4; // Delta of address + + for (; width; width--,sx+=8,tile+=delta) + { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal); + } + } +} +#endif // !_ASM_DRAW_C + +static void DrawSpritesHiAS(unsigned char *sprited, int sh) +{ + int (*fTileFunc)(int sx,int addr,int pal); + unsigned char *p; + int entry, cnt, sh_cnt = 0; + + cnt = sprited[0] & 0x7f; + if (cnt == 0) return; + + rendstatus |= PDRAW_SPR_LO_ON_HI; + + p = &sprited[3]; + + // Go through sprites: + for (entry = 0; entry < cnt; entry++) + { + int *sprite, code, pal, tile, sx, sy; + int offs, delta, width, height, row; + + offs = (p[entry] & 0x7f) * 2; + sprite = HighPreSpr + offs; + code = sprite[1]; + pal = (code>>9)&0x30; + + if (code & 0x8000) // hi priority + { + if (sh && pal == 0x30) + { + if (code&0x800) fTileFunc=TileFlipAS_noop; + else fTileFunc=TileNormAS_noop; + } else { + if (code&0x800) fTileFunc=TileFlipAS; + else fTileFunc=TileNormAS; + } + } else { + if (code&0x800) fTileFunc=TileFlipAS_onlymark; + else fTileFunc=TileNormAS_onlymark; + } + if (sh && pal == 0x30) + p[sh_cnt++] = offs / 2; // re-save for sh/hi pass + + // parse remaining sprite data + sy=sprite[0]; + sx=code>>16; // X + width=sy>>28; + height=(sy>>24)&7; // Width and height in tiles + sy=(sy<<16)>>16; // Y + + row=DrawScanline-sy; // Row of the sprite we are on + + if (code&0x1000) row=(height<<3)-1-row; // Flip Y + + tile=code + (row>>3); // Tile number increases going down + delta=height; // Delta to increase tile by going right + if (code&0x0800) { tile+=delta*(width-1); delta=-delta; } // Flip X + + tile &= 0x7ff; tile<<=4; tile+=(row&7)<<1; // Tile address + delta<<=4; // Delta of address + + pal |= 0x80; + for (; width; width--,sx+=8,tile+=delta) + { + if(sx<=0) continue; + if(sx>=328) break; // Offscreen + + tile&=0x7fff; // Clip tile address + fTileFunc(sx,tile,pal); + } + } + + if (!sh || !(sprited[1]&SPRL_MAY_HAVE_OP)) return; + + /* nasty 1: remove 'sprite' flags */ + { + int c = 320/4/4, *zb = (int *)(HighCol+8); + while (c--) + { + *zb++ &= 0x7f7f7f7f; *zb++ &= 0x7f7f7f7f; + *zb++ &= 0x7f7f7f7f; *zb++ &= 0x7f7f7f7f; + } + } + + /* nasty 2: sh operator pass */ + sprited[0] = sh_cnt; + DrawSpritesSHi(sprited); +} + + +// Index + 0 : ----hhvv -lllllll -------y yyyyyyyy +// Index + 4 : -------x xxxxxxxx pccvhnnn nnnnnnnn +// v +// Index + 0 : hhhhvvvv ----hhvv yyyyyyyy yyyyyyyy // v, h: vert./horiz. size +// Index + 4 : xxxxxxxx xxxxxxxx pccvhnnn nnnnnnnn // x: x coord + 8 + +void PrepareSprites(int full) +{ + struct PicoVideo *pvid=&Pico.video; + int u,link=0,sh; + int table=0; + int *pd = HighPreSpr; + int max_lines = 224, max_sprites = 80, max_width = 328; + int max_line_sprites = 20; // 20 sprites, 40 tiles + + if (!(Pico.video.reg[12]&1)) + max_sprites = 64, max_line_sprites = 16, max_width = 264; + if (PicoOpt & POPT_DIS_SPRITE_LIM) + max_line_sprites = MAX_LINE_SPRITES; + + if (pvid->reg[1]&8) max_lines = 240; + sh = Pico.video.reg[0xC]&8; // shadow/hilight? + + table=pvid->reg[5]&0x7f; + if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + table<<=8; // Get sprite table address/2 + + if (!full) + { + int pack; + // updates: tilecode, sx + for (u=0; u < max_sprites && (pack = *pd); u++, pd+=2) + { + unsigned int *sprite; + int code2, sx, sy, height; + + sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + + // parse sprite info + code2 = sprite[1]; + sx = (code2>>16)&0x1ff; + sx -= 0x78; // Get X coordinate + 8 + sy = (pack << 16) >> 16; + height = (pack >> 24) & 0xf; + + if (sy < max_lines && sy + (height<<3) > DrawScanline && // sprite onscreen (y)? + (sx > -24 || sx < max_width)) // onscreen x + { + int y = (sy >= DrawScanline) ? sy : DrawScanline; + int entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80); + for (; y < sy + (height<<3) && y < max_lines; y++) + { + int i, cnt; + cnt = HighLnSpr[y][0] & 0x7f; + if (cnt >= max_line_sprites) continue; // sprite limit? + + for (i = 0; i < cnt; i++) + if (((HighLnSpr[y][3+i] ^ entry) & 0x7f) == 0) goto found; + + // this sprite was previously missing + HighLnSpr[y][3+cnt] = entry; + HighLnSpr[y][0] = cnt + 1; +found:; + if (entry & 0x80) + HighLnSpr[y][1] |= SPRL_HAVE_HI; + else HighLnSpr[y][1] |= SPRL_HAVE_LO; + } + } + + code2 &= ~0xfe000000; + code2 -= 0x00780000; // Get X coordinate + 8 in upper 16 bits + pd[1] = code2; + + // Find next sprite + link=(sprite[0]>>16)&0x7f; + if (!link) break; // End of sprites + } + } + else + { + for (u = 0; u < max_lines; u++) + *((int *)&HighLnSpr[u][0]) = 0; + + for (u = 0; u < max_sprites; u++) + { + unsigned int *sprite; + int code, code2, sx, sy, hv, height, width; + + sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + + // parse sprite info + code = sprite[0]; + sy = (code&0x1ff)-0x80; + hv = (code>>24)&0xf; + height = (hv&3)+1; + + width = (hv>>2)+1; + code2 = sprite[1]; + sx = (code2>>16)&0x1ff; + sx -= 0x78; // Get X coordinate + 8 + + if (sy < max_lines && sy + (height<<3) > DrawScanline) // sprite onscreen (y)? + { + int entry, y, sx_min, onscr_x, maybe_op = 0; + + sx_min = 8-(width<<3); + onscr_x = sx_min < sx && sx < max_width; + if (sh && (code2 & 0x6000) == 0x6000) + maybe_op = SPRL_MAY_HAVE_OP; + + entry = ((pd - HighPreSpr) / 2) | ((code2>>8)&0x80); + y = (sy >= DrawScanline) ? sy : DrawScanline; + for (; y < sy + (height<<3) && y < max_lines; y++) + { + unsigned char *p = &HighLnSpr[y][0]; + int cnt = p[0]; + if (cnt >= max_line_sprites) continue; // sprite limit? + + if (p[2] >= max_line_sprites*2) { // tile limit? + p[0] |= 0x80; + continue; + } + p[2] += width; + + if (sx == -0x78) { + if (cnt > 0) + p[0] |= 0x80; // masked, no more sprites for this line + continue; + } + // must keep the first sprite even if it's offscreen, for masking + if (cnt > 0 && !onscr_x) continue; // offscreen x + + p[3+cnt] = entry; + p[0] = cnt + 1; + p[1] |= (entry & 0x80) ? SPRL_HAVE_HI : SPRL_HAVE_LO; + p[1] |= maybe_op; // there might be op sprites on this line + if (cnt > 0 && (code2 & 0x8000) && !(p[3+cnt-1]&0x80)) + p[1] |= SPRL_LO_ABOVE_HI; + } + } + + *pd++ = (width<<28)|(height<<24)|(hv<<16)|((unsigned short)sy); + *pd++ = (sx<<16)|((unsigned short)code2); + + // Find next sprite + link=(code>>16)&0x7f; + if (!link) break; // End of sprites + } + *pd = 0; + +#if 0 + for (u = 0; u < max_lines; u++) + { + int y; + printf("c%03i: %2i, %2i: ", u, HighLnSpr[u][0] & 0x7f, HighLnSpr[u][2]); + for (y = 0; y < HighLnSpr[u][0] & 0x7f; y++) + printf(" %i", HighLnSpr[u][y+3]); + printf("\n"); + } +#endif + } +} + +#ifndef _ASM_DRAW_C +static void DrawAllSprites(unsigned char *sprited, int prio, int sh) +{ + int rs = rendstatus; + unsigned char *p; + int cnt; + + if (rs & (PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES)) { + //elprintf(EL_STATUS, "PrepareSprites(%i)", (rs>>4)&1); + PrepareSprites(rs & PDRAW_DIRTY_SPRITES); + rendstatus = rs & ~(PDRAW_SPRITES_MOVED|PDRAW_DIRTY_SPRITES); + } + + cnt = sprited[0] & 0x7f; + if (cnt == 0) return; + + p = &sprited[3]; + + // Go through sprites backwards: + for (cnt--; cnt >= 0; cnt--) + { + int offs; + if ((p[cnt] >> 7) != prio) continue; + offs = (p[cnt]&0x7f) * 2; + DrawSprite(HighPreSpr + offs, sh); + } +} + + +// -------------------------------------------- + +void BackFill(int reg7, int sh) +{ + unsigned int back; + + // Start with a blank scanline (background colour): + back=reg7&0x3f; + back|=sh<<6; + back|=back<<8; + back|=back<<16; + + memset32((int *)(HighCol+8), back, 320/4); +} +#endif + +// -------------------------------------------- + +unsigned short HighPal[0x100]; + +#ifndef _ASM_DRAW_C +void PicoDoHighPal555(int sh) +{ + unsigned int *spal, *dpal; + unsigned int t, i; + + Pico.m.dirtyPal = 0; + + spal = (void *)Pico.cram; + dpal = (void *)HighPal; + + for (i = 0; i < 0x40 / 2; i++) { + t = spal[i]; +#ifdef USE_BGR555 + t = ((t & 0x000e000e)<< 1) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)<<4); +#else + t = ((t & 0x000e000e)<<12) | ((t & 0x00e000e0)<<3) | ((t & 0x0e000e00)>>7); +#endif + // treat it like it was 4-bit per channel, since in s/h mode it somewhat is that. + // otherwise intensity difference between this and s/h will be wrong + t |= (t >> 4) & 0x08610861; // 0x18e318e3 + dpal[i] = t; + } + + // norm: xxx0, sh: 0xxx, hi: 0xxx + 7 + if (sh) + { + // shadowed pixels + for (i = 0; i < 0x40 / 2; i++) + dpal[0x40/2 | i] = dpal[0xc0/2 | i] = (dpal[i] >> 1) & 0x738e738e; + // hilighted pixels + for (i = 0; i < 0x40 / 2; i++) { + t = ((dpal[i] >> 1) & 0x738e738e) + 0x738e738e; // 0x7bef7bef; + t |= (t >> 4) & 0x08610861; + dpal[0x80/2 | i] = t; + } + } +} + +#if 0 +static void FinalizeLineBGR444(int sh, int line) +{ + unsigned short *pd=DrawLineDest; + unsigned char *ps=HighCol+8; + unsigned short *pal=Pico.cram; + int len, i, t, mask=0xff; + + if (Pico.video.reg[12]&1) { + len = 320; + } else { + if(!(PicoOpt&POPT_DIS_32C_BORDER)) pd+=32; + len = 256; + } + + if(sh) { + pal=HighPal; + if(Pico.m.dirtyPal) { + blockcpy(pal, Pico.cram, 0x40*2); + // shadowed pixels + for(i = 0x3f; i >= 0; i--) + pal[0x40|i] = pal[0xc0|i] = (unsigned short)((pal[i]>>1)&0x0777); + // hilighted pixels + for(i = 0x3f; i >= 0; i--) { + t=pal[i]&0xeee;t+=0x444;if(t&0x10)t|=0xe;if(t&0x100)t|=0xe0;if(t&0x1000)t|=0xe00;t&=0xeee; + pal[0x80|i]=(unsigned short)t; + } + Pico.m.dirtyPal = 0; + } + } + + if (!sh && (rendstatus & PDRAW_SPR_LO_ON_HI)) + mask=0x3f; // accurate sprites + + for(i = 0; i < len; i++) + pd[i] = pal[ps[i] & mask]; +} +#endif + + +void FinalizeLine555(int sh, int line) +{ + unsigned short *pd=DrawLineDest; + unsigned char *ps=HighCol+8; + unsigned short *pal=HighPal; + int len; + + if (Pico.m.dirtyPal) + PicoDoHighPal555(sh); + + if (Pico.video.reg[12]&1) { + len = 320; + } else { + if (!(PicoOpt&POPT_DIS_32C_BORDER)) pd+=32; + len = 256; + } + + { +#ifndef PSP + int i, mask=0xff; + if (!sh && (rendstatus & PDRAW_SPR_LO_ON_HI)) + mask=0x3f; // accurate sprites, upper bits are priority stuff + + for (i = 0; i < len; i++) + pd[i] = pal[ps[i] & mask]; +#else + extern void amips_clut(unsigned short *dst, unsigned char *src, unsigned short *pal, int count); + extern void amips_clut_6bit(unsigned short *dst, unsigned char *src, unsigned short *pal, int count); + if (!sh && (rendstatus & PDRAW_SPR_LO_ON_HI)) + amips_clut_6bit(pd, ps, pal, len); + else amips_clut(pd, ps, pal, len); +#endif + } +} +#endif + +static void FinalizeLine8bit(int sh, int line) +{ + unsigned char *pd = DrawLineDest; + int len, rs = rendstatus; + static int dirty_count; + + if (!sh && Pico.m.dirtyPal == 1) + { + // a hack for mid-frame palette changes + if (!(rs & PDRAW_SONIC_MODE)) + dirty_count = 1; + else dirty_count++; + rs |= PDRAW_SONIC_MODE; + rendstatus = rs; + if (dirty_count == 3) { + blockcpy(HighPal, Pico.cram, 0x40*2); + } else if (dirty_count == 11) { + blockcpy(HighPal+0x40, Pico.cram, 0x40*2); + } + } + + if (Pico.video.reg[12]&1) { + len = 320; + } else { + if (!(PicoOpt & POPT_DIS_32C_BORDER)) + pd += 32; + len = 256; + } + + if (!sh && (rs & PDRAW_SONIC_MODE)) { + if (dirty_count >= 11) { + blockcpy_or(pd, HighCol+8, len, 0x80); + } else { + blockcpy_or(pd, HighCol+8, len, 0x40); + } + } else { + blockcpy(pd, HighCol+8, len); + } +} + +static void (*FinalizeLine)(int sh, int line); + +// -------------------------------------------- + +static int DrawDisplay(int sh) +{ + unsigned char *sprited = &HighLnSpr[DrawScanline][0]; + struct PicoVideo *pvid=&Pico.video; + int win=0,edge=0,hvwind=0; + int maxw,maxcells; + + rendstatus &= ~(PDRAW_SHHI_DONE|PDRAW_PLANE_HI_PRIO); + + if (pvid->reg[12]&1) { + maxw = 328; maxcells = 40; + } else { + maxw = 264; maxcells = 32; + } + + // Find out if the window is on this line: + win=pvid->reg[0x12]; + edge=(win&0x1f)<<3; + + if (win&0x80) { if (DrawScanline>=edge) hvwind=1; } + else { if (DrawScanline< edge) hvwind=1; } + + if (!hvwind) // we might have a vertical window here + { + win=pvid->reg[0x11]; + edge=win&0x1f; + if (win&0x80) { + if (!edge) hvwind=1; + else if(edge < (maxcells>>1)) hvwind=2; + } else { + if (!edge); + else if(edge < (maxcells>>1)) hvwind=2; + else hvwind=1; + } + } + + /* - layer B low - */ + if (PicoDrawMask & PDRAW_LAYERB_ON) + DrawLayer(1|(sh<<1), HighCacheB, 0, maxcells); + /* - layer A low - */ + if (!(PicoDrawMask & PDRAW_LAYERA_ON)); + else if (hvwind == 1) + DrawWindow(0, maxcells>>1, 0, sh); + else if (hvwind == 2) { + DrawLayer(0|(sh<<1), HighCacheA, (win&0x80) ? 0 : edge<<1, (win&0x80) ? edge<<1 : maxcells); + DrawWindow( (win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 0, sh); + } else + DrawLayer(0|(sh<<1), HighCacheA, 0, maxcells); + /* - sprites low - */ + if (!(PicoDrawMask & PDRAW_SPRITES_LOW_ON)); + else if (rendstatus & PDRAW_INTERLACE) + DrawAllSpritesInterlace(0, sh); + else if (sprited[1] & SPRL_HAVE_LO) + DrawAllSprites(sprited, 0, sh); + + /* - layer B hi - */ + if ((PicoDrawMask & PDRAW_LAYERB_ON) && HighCacheB[0]) + DrawTilesFromCache(HighCacheB, sh, maxw); + /* - layer A hi - */ + if (!(PicoDrawMask & PDRAW_LAYERA_ON)); + else if (hvwind == 1) + DrawWindow(0, maxcells>>1, 1, sh); + else if (hvwind == 2) { + if (HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh, (win&0x80) ? edge<<4 : maxw); + DrawWindow((win&0x80) ? edge : 0, (win&0x80) ? maxcells>>1 : edge, 1, sh); + } else + if (HighCacheA[0]) DrawTilesFromCache(HighCacheA, sh, maxw); + /* - sprites hi - */ + if (!(PicoDrawMask & PDRAW_SPRITES_HI_ON)); + else if (rendstatus & PDRAW_INTERLACE) + DrawAllSpritesInterlace(1, sh); + // have sprites without layer pri bit ontop of sprites with that bit + else if ((sprited[1] & 0xd0) == 0xd0 && (PicoOpt & POPT_ACC_SPRITES)) + DrawSpritesHiAS(sprited, sh); + else if (sh && (sprited[1] & SPRL_MAY_HAVE_OP)) + DrawSpritesSHi(sprited); + else if (sprited[1] & SPRL_HAVE_HI) + DrawAllSprites(sprited, 1, 0); + +#if 0 + { + int *c, a, b; + for (a = 0, c = HighCacheA; *c; c++, a++); + for (b = 0, c = HighCacheB; *c; c++, b++); + printf("%i:%03i: a=%i, b=%i\n", Pico.m.frame_count, DrawScanline, a, b); + } +#endif + + return 0; +} + +// MUST be called every frame +PICO_INTERNAL void PicoFrameStart(void) +{ + int offs = 8, lines = 224; + + // prepare to do this frame + rendstatus = 0; + if ((Pico.video.reg[12] & 6) == 6) + rendstatus |= PDRAW_INTERLACE; // interlace mode + if (!(Pico.video.reg[12] & 1)) + rendstatus |= PDRAW_32_COLS; + if (Pico.video.reg[1] & 8) { + offs = 0; + lines = 240; + } + + if (rendstatus != rendstatus_old || lines != rendlines) { + rendlines = lines; + // mode_change() might reset rendstatus_old by calling SetColorFormat + emu_video_mode_change((lines == 240) ? 0 : 8, + lines, (Pico.video.reg[12] & 1) ? 0 : 1); + rendstatus_old = rendstatus; + } + + HighCol = HighColBase + offs * HighColIncrement; + DrawLineDest = (char *)DrawLineDestBase + offs * DrawLineDestIncrement; + DrawScanline = 0; + skip_next_line = 0; + + if (PicoOpt & POPT_ALT_RENDERER) + return; + + if (Pico.m.dirtyPal) + Pico.m.dirtyPal = 2; // reset dirty if needed + PrepareSprites(1); +} + +static void DrawBlankedLine(int line, int offs, int sh, int bgc) +{ + if (PicoScanBegin != NULL) + PicoScanBegin(line + offs); + + BackFill(bgc, sh); + + if (FinalizeLine != NULL) + FinalizeLine(sh, line); + + if (PicoScanEnd != NULL) + PicoScanEnd(line + offs); + + HighCol += HighColIncrement; + DrawLineDest = (char *)DrawLineDest + DrawLineDestIncrement; +} + +static void PicoLine(int line, int offs, int sh, int bgc) +{ + int skip = 0; + + if (skip_next_line > 0) { + skip_next_line--; + return; + } + + DrawScanline = line; + if (PicoScanBegin != NULL) + skip = PicoScanBegin(line + offs); + + if (skip) { + skip_next_line = skip - 1; + return; + } + + // Draw screen: + BackFill(bgc, sh); + if (Pico.video.reg[1]&0x40) + DrawDisplay(sh); + + if (FinalizeLine != NULL) + FinalizeLine(sh, line); + + if (PicoScanEnd != NULL) + skip_next_line = PicoScanEnd(line + offs); + + HighCol += HighColIncrement; + DrawLineDest = (char *)DrawLineDest + DrawLineDestIncrement; +} + +void PicoDrawSync(int to, int blank_last_line) +{ + int line, offs = 0; + int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight? + int bgc = Pico.video.reg[7]; + + pprof_start(draw); + + if (rendlines != 240) + offs = 8; + + for (line = DrawScanline; line < to; line++) + { + PicoLine(line, offs, sh, bgc); + } + + // last line + if (line <= to) + { + if (blank_last_line) + DrawBlankedLine(line, offs, sh, bgc); + else PicoLine(line, offs, sh, bgc); + line++; + } + DrawScanline = line; + + pprof_end(draw); +} + +// also works for fast renderer +void PicoDrawUpdateHighPal(void) +{ + int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight? + if (PicoOpt & POPT_ALT_RENDERER) + sh = 0; // no s/h support + + PicoDoHighPal555(sh); + if (rendstatus & PDRAW_SONIC_MODE) { + // FIXME? + memcpy(HighPal + 0x40, HighPal, 0x40*2); + memcpy(HighPal + 0x80, HighPal, 0x40*2); + } +} + +void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode) +{ + switch (which) + { + case PDF_8BIT: + FinalizeLine = FinalizeLine8bit; + break; + + case PDF_RGB555: + if ((PicoAHW & PAHW_32X) && use_32x_line_mode) + FinalizeLine = FinalizeLine32xRGB555; + else + FinalizeLine = FinalizeLine555; + break; + + default: + FinalizeLine = NULL; + break; + } + PicoDrawSetOutFormat32x(which, use_32x_line_mode); + PicoDrawSetOutputMode4(which); + rendstatus_old = -1; +} + +// note: may be called on the middle of frame +void PicoDrawSetOutBuf(void *dest, int increment) +{ + DrawLineDestBase = dest; + DrawLineDestIncrement = increment; + DrawLineDest = DrawLineDestBase + DrawScanline * increment; +} + +void PicoDrawSetInternalBuf(void *dest, int increment) +{ + if (dest != NULL) { + HighColBase = dest; + HighColIncrement = increment; + HighCol = HighColBase + DrawScanline * increment; + } + else { + HighColBase = DefHighCol; + HighColIncrement = 0; + } +} + +void PicoDrawSetCallbacks(int (*begin)(unsigned int num), int (*end)(unsigned int num)) +{ + PicoScanBegin = NULL; + PicoScanEnd = NULL; + PicoScan32xBegin = NULL; + PicoScan32xEnd = NULL; + + if ((PicoAHW & PAHW_32X) && FinalizeLine != FinalizeLine32xRGB555) { + PicoScan32xBegin = begin; + PicoScan32xEnd = end; + } + else { + PicoScanBegin = begin; + PicoScanEnd = end; + } +} diff --git a/waterbox/picodrive/pico/draw2.c b/waterbox/picodrive/pico/draw2.c new file mode 100644 index 0000000000..5730d7b6d7 --- /dev/null +++ b/waterbox/picodrive/pico/draw2.c @@ -0,0 +1,624 @@ +/* + * tile renderer + * (C) notaz, 2006-2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" + +#define START_ROW 0 // which row of tiles to start rendering at? +#define END_ROW 28 // ..end + +#define TILE_ROWS END_ROW-START_ROW + +// note: this is not implemented in ARM asm +#if defined(DRAW2_OVERRIDE_LINE_WIDTH) +#define LINE_WIDTH DRAW2_OVERRIDE_LINE_WIDTH +#else +#define LINE_WIDTH 328 +#endif + +static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)]; +unsigned char *PicoDraw2FB = PicoDraw2FB_; + +static int HighCache2A[41*(TILE_ROWS+1)+1+1]; // caches for high layers +static int HighCache2B[41*(TILE_ROWS+1)+1+1]; + +unsigned short *PicoCramHigh=Pico.cram; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now) +void (*PicoPrepareCram)()=0; // prepares PicoCramHigh for renderer to use + + +// stuff available in asm: +#ifdef _ASM_DRAW_C +void BackFillFull(int reg7); +void DrawLayerFull(int plane, int *hcache, int planestart, int planeend); +void DrawTilesFromCacheF(int *hc); +void DrawWindowFull(int start, int end, int prio); +void DrawSpriteFull(unsigned int *sprite); +#else + + +static int TileXnormYnorm(unsigned char *pd,int addr,unsigned char pal) +{ + unsigned int pack=0; unsigned int t=0, blank = 1; + int i; + + for(i=8; i; i--, addr+=2, pd += LINE_WIDTH) { + pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + if(!pack) continue; + + t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); + t=pack&0x00000f00; if (t) pd[1]=(unsigned char)((t>> 8)|pal); + t=pack&0x000000f0; if (t) pd[2]=(unsigned char)((t>> 4)|pal); + t=pack&0x0000000f; if (t) pd[3]=(unsigned char)((t )|pal); + t=pack&0xf0000000; if (t) pd[4]=(unsigned char)((t>>28)|pal); + t=pack&0x0f000000; if (t) pd[5]=(unsigned char)((t>>24)|pal); + t=pack&0x00f00000; if (t) pd[6]=(unsigned char)((t>>20)|pal); + t=pack&0x000f0000; if (t) pd[7]=(unsigned char)((t>>16)|pal); + blank = 0; + } + + return blank; // Tile blank? +} + +static int TileXflipYnorm(unsigned char *pd,int addr,unsigned char pal) +{ + unsigned int pack=0; unsigned int t=0, blank = 1; + int i; + + for(i=8; i; i--, addr+=2, pd += LINE_WIDTH) { + pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + if(!pack) continue; + + t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); + t=pack&0x00f00000; if (t) pd[1]=(unsigned char)((t>>20)|pal); + t=pack&0x0f000000; if (t) pd[2]=(unsigned char)((t>>24)|pal); + t=pack&0xf0000000; if (t) pd[3]=(unsigned char)((t>>28)|pal); + t=pack&0x0000000f; if (t) pd[4]=(unsigned char)((t )|pal); + t=pack&0x000000f0; if (t) pd[5]=(unsigned char)((t>> 4)|pal); + t=pack&0x00000f00; if (t) pd[6]=(unsigned char)((t>> 8)|pal); + t=pack&0x0000f000; if (t) pd[7]=(unsigned char)((t>>12)|pal); + blank = 0; + } + return blank; // Tile blank? +} + +static int TileXnormYflip(unsigned char *pd,int addr,unsigned char pal) +{ + unsigned int pack=0; unsigned int t=0, blank = 1; + int i; + + addr+=14; + for(i=8; i; i--, addr-=2, pd += LINE_WIDTH) { + pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + if(!pack) continue; + + t=pack&0x0000f000; if (t) pd[0]=(unsigned char)((t>>12)|pal); + t=pack&0x00000f00; if (t) pd[1]=(unsigned char)((t>> 8)|pal); + t=pack&0x000000f0; if (t) pd[2]=(unsigned char)((t>> 4)|pal); + t=pack&0x0000000f; if (t) pd[3]=(unsigned char)((t )|pal); + t=pack&0xf0000000; if (t) pd[4]=(unsigned char)((t>>28)|pal); + t=pack&0x0f000000; if (t) pd[5]=(unsigned char)((t>>24)|pal); + t=pack&0x00f00000; if (t) pd[6]=(unsigned char)((t>>20)|pal); + t=pack&0x000f0000; if (t) pd[7]=(unsigned char)((t>>16)|pal); + blank = 0; + } + + return blank; // Tile blank? +} + +static int TileXflipYflip(unsigned char *pd,int addr,unsigned char pal) +{ + unsigned int pack=0; unsigned int t=0, blank = 1; + int i; + + addr+=14; + for(i=8; i; i--, addr-=2, pd += LINE_WIDTH) { + pack=*(unsigned int *)(Pico.vram+addr); // Get 8 pixels + if(!pack) continue; + + t=pack&0x000f0000; if (t) pd[0]=(unsigned char)((t>>16)|pal); + t=pack&0x00f00000; if (t) pd[1]=(unsigned char)((t>>20)|pal); + t=pack&0x0f000000; if (t) pd[2]=(unsigned char)((t>>24)|pal); + t=pack&0xf0000000; if (t) pd[3]=(unsigned char)((t>>28)|pal); + t=pack&0x0000000f; if (t) pd[4]=(unsigned char)((t )|pal); + t=pack&0x000000f0; if (t) pd[5]=(unsigned char)((t>> 4)|pal); + t=pack&0x00000f00; if (t) pd[6]=(unsigned char)((t>> 8)|pal); + t=pack&0x0000f000; if (t) pd[7]=(unsigned char)((t>>12)|pal); + blank = 0; + } + return blank; // Tile blank? +} + + +// start: (tile_start<<16)|row_start, end: [same] +static void DrawWindowFull(int start, int end, int prio) +{ + struct PicoVideo *pvid=&Pico.video; + int nametab, nametab_step, trow, tilex, blank=-1, code; + unsigned char *scrpos = PicoDraw2FB; + int tile_start, tile_end; // in cells + + // parse ranges + tile_start = start>>16; + tile_end = end>>16; + start = start<<16>>16; + end = end<<16>>16; + + // Find name table line: + if (pvid->reg[12]&1) + { + nametab=(pvid->reg[3]&0x3c)<<9; // 40-cell mode + nametab_step = 1<<6; + } + else + { + nametab=(pvid->reg[3]&0x3e)<<9; // 32-cell mode + nametab_step = 1<<5; + } + nametab += nametab_step*start; + + // check priority + code=Pico.vram[nametab+tile_start]; + if ((code>>15) != prio) return; // hack: just assume that whole window uses same priority + + scrpos+=8*LINE_WIDTH+8; + scrpos+=8*LINE_WIDTH*(start-START_ROW); + + // do a window until we reach planestart row + for(trow = start; trow < end; trow++, nametab+=nametab_step) { // current tile row + for (tilex=tile_start; tilex>9)&0x30); + pal=(unsigned char)((code>>9)&0x30); + + switch((code>>11)&3) { + case 0: zero=TileXnormYnorm(scrpos+(tilex<<3),addr,pal); break; + case 1: zero=TileXflipYnorm(scrpos+(tilex<<3),addr,pal); break; + case 2: zero=TileXnormYflip(scrpos+(tilex<<3),addr,pal); break; + case 3: zero=TileXflipYflip(scrpos+(tilex<<3),addr,pal); break; + } + if(zero) blank=code; // We know this tile is blank now + } + + scrpos += LINE_WIDTH*8; + } +} + + +static void DrawLayerFull(int plane, int *hcache, int planestart, int planeend) +{ + struct PicoVideo *pvid=&Pico.video; + static char shift[4]={5,6,6,7}; // 32,64 or 128 sized tilemaps + int width, height, ymask, htab; + int nametab, hscroll=0, vscroll, cells; + unsigned char *scrpos; + int blank=-1, xmask, nametab_row, trow; + + // parse ranges + cells = (planeend>>16)-(planestart>>16); + planestart = planestart<<16>>16; + planeend = planeend<<16>>16; + + // Work out the Tiles to draw + + htab=pvid->reg[13]<<9; // Horizontal scroll table address +// if ( pvid->reg[11]&2) htab+=Scanline<<1; // Offset by line +// if ((pvid->reg[11]&1)==0) htab&=~0xf; // Offset by tile + htab+=plane; // A or B + + if(!(pvid->reg[11]&3)) { // full screen scroll + // Get horizontal scroll value + hscroll=Pico.vram[htab&0x7fff]; + htab = 0; // this marks that we don't have to update scroll value + } + + // Work out the name table size: 32 64 or 128 tiles (0-3) + width=pvid->reg[16]; + height=(width>>4)&3; width&=3; + + xmask=(1<1) ymask =0x1f; + + // Find name table: + if (plane==0) nametab=(pvid->reg[2]&0x38)<< 9; // A + else nametab=(pvid->reg[4]&0x07)<<12; // B + + scrpos = PicoDraw2FB; + scrpos+=8*LINE_WIDTH*(planestart-START_ROW); + + // Get vertical scroll value: + vscroll=Pico.vsram[plane]&0x1ff; + scrpos+=(8-(vscroll&7))*LINE_WIDTH; + if(vscroll&7) planeend++; // we have vertically clipped tiles due to vscroll, so we need 1 more row + + *hcache++ = 8-(vscroll&7); // push y-offset to tilecache + + + for(trow = planestart; trow < planeend; trow++) { // current tile row + int cellc=cells,tilex,dx; + + // Find the tile row in the name table + //ts.line=(vscroll+Scanline)&ymask; + //ts.nametab+=(ts.line>>3)<>3))&ymask)<>3; + dx=((hscroll-1)&7)+1; + if(dx != 8) cellc++; // have hscroll, do more cells + + for (; cellc; dx+=8,tilex++,cellc--) + { + int code=0,addr=0,zero=0; +// unsigned short *pal=NULL; + unsigned char pal; + + code=Pico.vram[nametab_row+(tilex&xmask)]; + if (code==blank) continue; + + if (code>>15) { // high priority tile + *hcache++ = code|(dx<<16)|(trow<<27); // cache it + continue; + } + + // Get tile address/2: + addr=(code&0x7ff)<<4; + +// pal=PicoCramHigh+((code>>9)&0x30); + pal=(unsigned char)((code>>9)&0x30); + + switch((code>>11)&3) { + case 0: zero=TileXnormYnorm(scrpos+dx,addr,pal); break; + case 1: zero=TileXflipYnorm(scrpos+dx,addr,pal); break; + case 2: zero=TileXnormYflip(scrpos+dx,addr,pal); break; + case 3: zero=TileXflipYflip(scrpos+dx,addr,pal); break; + } + if(zero) blank=code; // We know this tile is blank now + } + + scrpos += LINE_WIDTH*8; + } + + *hcache = 0; // terminate cache +} + + +static void DrawTilesFromCacheF(int *hc) +{ + int code, addr, zero = 0; + unsigned int prevy=0xFFFFFFFF; +// unsigned short *pal; + unsigned char pal; + short blank=-1; // The tile we know is blank + unsigned char *scrpos = PicoDraw2FB, *pd = 0; + + // *hcache++ = code|(dx<<16)|(trow<<27); // cache it + scrpos+=(*hc++)*LINE_WIDTH - START_ROW*LINE_WIDTH*8; + + while((code=*hc++)) { + if((short)code == blank) continue; + + // y pos + if(((unsigned)code>>27) != prevy) { + prevy = (unsigned)code>>27; + pd = scrpos + prevy*LINE_WIDTH*8; + } + + // Get tile address/2: + addr=(code&0x7ff)<<4; +// pal=PicoCramHigh+((code>>9)&0x30); + pal=(unsigned char)((code>>9)&0x30); + + switch((code>>11)&3) { + case 0: zero=TileXnormYnorm(pd+((code>>16)&0x1ff),addr,pal); break; + case 1: zero=TileXflipYnorm(pd+((code>>16)&0x1ff),addr,pal); break; + case 2: zero=TileXnormYflip(pd+((code>>16)&0x1ff),addr,pal); break; + case 3: zero=TileXflipYflip(pd+((code>>16)&0x1ff),addr,pal); break; + } + + if(zero) blank=(short)code; + } +} + + +// sx and sy are coords of virtual screen with 8pix borders on top and on left +static void DrawSpriteFull(unsigned int *sprite) +{ + int width=0,height=0; +// unsigned short *pal=NULL; + unsigned char pal; + int tile,code,tdeltax,tdeltay; + unsigned char *scrpos; + int sx, sy; + + sy=sprite[0]; + height=sy>>24; + sy=(sy&0x1ff)-0x78; // Y + width=(height>>2)&3; height&=3; + width++; height++; // Width and height in tiles + + code=sprite[1]; + sx=((code>>16)&0x1ff)-0x78; // X + + tile=code&0x7ff; // Tile number + tdeltax=height; // Delta to increase tile by going right + tdeltay=1; // Delta to increase tile by going down + if (code&0x0800) { tdeltax=-tdeltax; tile+=height*(width-1); } // Flip X + if (code&0x1000) { tdeltay=-tdeltay; tile+=height-1; } // Flip Y + + //delta<<=4; // Delta of address +// pal=PicoCramHigh+((code>>9)&0x30); // Get palette pointer + pal=(unsigned char)((code>>9)&0x30); + + // goto first vertically visible tile + while(sy <= START_ROW*8) { sy+=8; tile+=tdeltay; height--; } + + scrpos = PicoDraw2FB; + scrpos+=(sy-START_ROW*8)*LINE_WIDTH; + + for (; height > 0; height--, sy+=8, tile+=tdeltay) + { + int w = width, x=sx, t=tile; + + if(sy >= END_ROW*8+8) return; // offscreen + + for (; w; w--,x+=8,t+=tdeltax) + { + if(x<=0) continue; + if(x>=328) break; // Offscreen + + t&=0x7fff; // Clip tile address + switch((code>>11)&3) { + case 0: TileXnormYnorm(scrpos+x,t<<4,pal); break; + case 1: TileXflipYnorm(scrpos+x,t<<4,pal); break; + case 2: TileXnormYflip(scrpos+x,t<<4,pal); break; + case 3: TileXflipYflip(scrpos+x,t<<4,pal); break; + } + } + + scrpos+=8*LINE_WIDTH; + } +} +#endif + + +static void DrawAllSpritesFull(int prio, int maxwidth) +{ + struct PicoVideo *pvid=&Pico.video; + int table=0,maskrange=0; + int i,u,link=0; + unsigned int *sprites[80]; // Sprites + int y_min=START_ROW*8, y_max=END_ROW*8; // for a simple sprite masking + + table=pvid->reg[5]&0x7f; + if (pvid->reg[12]&1) table&=0x7e; // Lowest bit 0 in 40-cell mode + table<<=8; // Get sprite table address/2 + + for (i=u=0; u < 80; u++) + { + unsigned int *sprite=NULL; + int code, code2, sx, sy, height; + + sprite=(unsigned int *)(Pico.vram+((table+(link<<2))&0x7ffc)); // Find sprite + + // get sprite info + code = sprite[0]; + + // check if it is not hidden vertically + sy = (code&0x1ff)-0x80; + height = (((code>>24)&3)+1)<<3; + if(sy+height <= y_min || sy > y_max) goto nextsprite; + + // masking sprite? + code2=sprite[1]; + sx = (code2>>16)&0x1ff; + if(!sx) { + int to = sy+height; // sy ~ from + if(maskrange) { + // try to merge with previous range + if((maskrange>>16)+1 >= sy && (maskrange>>16) <= to && (maskrange&0xffff) < sy) sy = (maskrange&0xffff); + else if((maskrange&0xffff)-1 <= to && (maskrange&0xffff) >= sy && (maskrange>>16) > to) to = (maskrange>>16); + } + // support only very simple masking (top and bottom of screen) + if(sy <= y_min && to+1 > y_min) y_min = to+1; + else if(to >= y_max && sy-1 < y_max) y_max = sy-1; + else maskrange=sy|(to<<16); + + goto nextsprite; + } + + // priority + if(((code2>>15)&1) != prio) goto nextsprite; // wrong priority + + // check if sprite is not hidden horizontally + sx -= 0x78; // Get X coordinate + 8 + if(sx <= -8*3 || sx >= maxwidth) goto nextsprite; + + // sprite is good, save it's index + sprites[i++]=sprite; + + nextsprite: + // Find next sprite + link=(code>>16)&0x7f; + if(!link) break; // End of sprites + } + + // Go through sprites backwards: + for (i-- ;i>=0; i--) + { + DrawSpriteFull(sprites[i]); + } +} + +#ifndef _ASM_DRAW_C +static void BackFillFull(int reg7) +{ + unsigned int back; + + // Start with a background color: +// back=PicoCramHigh[reg7&0x3f]; + back=reg7&0x3f; + back|=back<<8; + back|=back<<16; + + memset32((int *)PicoDraw2FB, back, LINE_WIDTH*(8+(END_ROW-START_ROW)*8)/4); +} +#endif + +static void DrawDisplayFull(void) +{ + struct PicoVideo *pvid=&Pico.video; + int win, edge=0, hvwin=0; // LSb->MSb: hwin&plane, vwin&plane, full + int planestart=START_ROW, planeend=END_ROW; // plane A start/end when window shares display with plane A (in tile rows or columns) + int winstart=START_ROW, winend=END_ROW; // same for window + int maxw, maxcolc; // max width and col cells + + if(pvid->reg[12]&1) { + maxw = 328; maxcolc = 40; + } else { + maxw = 264; maxcolc = 32; + } + + // horizontal window? + if ((win=pvid->reg[0x12])) + { + hvwin=1; // hwindow shares display with plane A + edge=win&0x1f; + if(win == 0x80) { + // fullscreen window + hvwin=4; + } else if(win < 0x80) { + // window on the top + if(edge <= START_ROW) hvwin=0; // window not visible in our drawing region + else if(edge >= END_ROW) hvwin=4; + else planestart = winend = edge; + } else if(win > 0x80) { + // window at the bottom + if(edge >= END_ROW) hvwin=0; + else planeend = winstart = edge; + } + } + + // check for vertical window, but only if win is not fullscreen + if (hvwin != 4) + { + win=pvid->reg[0x11]; + edge=win&0x1f; + if (win&0x80) { + if(!edge) hvwin=4; + else if(edge < (maxcolc>>1)) { + // window is on the right + hvwin|=2; + planeend|=edge<<17; + winstart|=edge<<17; + winend|=maxcolc<<16; + } + } else { + if(edge >= (maxcolc>>1)) hvwin=4; + else if(edge) { + // window is on the left + hvwin|=2; + winend|=edge<<17; + planestart|=edge<<17; + planeend|=maxcolc<<16; + } + } + } + + if (hvwin==1) { winend|=maxcolc<<16; planeend|=maxcolc<<16; } + + HighCache2A[1] = HighCache2B[1] = 0; + if (PicoDrawMask & PDRAW_LAYERB_ON) + DrawLayerFull(1, HighCache2B, START_ROW, (maxcolc<<16)|END_ROW); + if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin) + { + case 4: + // fullscreen window + DrawWindowFull(START_ROW, (maxcolc<<16)|END_ROW, 0); + break; + + case 3: + // we have plane A and both v and h windows + DrawLayerFull(0, HighCache2A, planestart, planeend); + DrawWindowFull( winstart&~0xff0000, (winend&~0xff0000)|(maxcolc<<16), 0); // h + DrawWindowFull((winstart&~0xff)|START_ROW, (winend&~0xff)|END_ROW, 0); // v + break; + + case 2: + case 1: + // both window and plane A visible, window is vertical XOR horizontal + DrawLayerFull(0, HighCache2A, planestart, planeend); + DrawWindowFull(winstart, winend, 0); + break; + + default: + // fullscreen plane A + DrawLayerFull(0, HighCache2A, START_ROW, (maxcolc<<16)|END_ROW); + break; + } + if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) + DrawAllSpritesFull(0, maxw); + + if (HighCache2B[1]) DrawTilesFromCacheF(HighCache2B); + if (HighCache2A[1]) DrawTilesFromCacheF(HighCache2A); + if (PicoDrawMask & PDRAW_LAYERA_ON) switch (hvwin) + { + case 4: + // fullscreen window + DrawWindowFull(START_ROW, (maxcolc<<16)|END_ROW, 1); + break; + + case 3: + // we have plane A and both v and h windows + DrawWindowFull( winstart&~0xff0000, (winend&~0xff0000)|(maxcolc<<16), 1); // h + DrawWindowFull((winstart&~0xff)|START_ROW, (winend&~0xff)|END_ROW, 1); // v + break; + + case 2: + case 1: + // both window and plane A visible, window is vertical XOR horizontal + DrawWindowFull(winstart, winend, 1); + break; + } + if (PicoDrawMask & PDRAW_SPRITES_HI_ON) + DrawAllSpritesFull(1, maxw); +} + + +PICO_INTERNAL void PicoFrameFull() +{ + pprof_start(draw); + + // prepare cram? + if (PicoPrepareCram) PicoPrepareCram(); + + // Draw screen: + BackFillFull(Pico.video.reg[7]); + if (Pico.video.reg[1] & 0x40) + DrawDisplayFull(); + + pprof_end(draw); +} + diff --git a/waterbox/picodrive/pico/eeprom.c b/waterbox/picodrive/pico/eeprom.c new file mode 100644 index 0000000000..16f6c05c45 --- /dev/null +++ b/waterbox/picodrive/pico/eeprom.c @@ -0,0 +1,212 @@ +/* + * rarely used EEPROM code + * (C) notaz, 2007-2009 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + * + * (see Genesis Plus for Wii/GC code and docs for info, + * full game list and better code). + */ + +#include "pico_int.h" + +static unsigned int last_write = 0xffff0000; + +// eeprom_status: LA.. s.la (L=pending SCL, A=pending SDA, +// s=started, l=old SCL, a=old SDA) +static void EEPROM_write_do(unsigned int d) // ???? ??la (l=SCL, a=SDA) +{ + unsigned int sreg = Pico.m.eeprom_status, saddr = Pico.m.eeprom_addr; + unsigned int scyc = Pico.m.eeprom_cycle, ssa = Pico.m.eeprom_slave; + + elprintf(EL_EEPROM, "eeprom: scl/sda: %i/%i -> %i/%i, newtime=%i", (sreg&2)>>1, sreg&1, + (d&2)>>1, d&1, SekCyclesDone() - last_write); + saddr &= 0x1fff; + + if(sreg & d & 2) { + // SCL was and is still high.. + if((sreg & 1) && !(d&1)) { + // ..and SDA went low, means it's a start command, so clear internal addr reg and clock counter + elprintf(EL_EEPROM, "eeprom: -start-"); + //saddr = 0; + scyc = 0; + sreg |= 8; + } else if(!(sreg & 1) && (d&1)) { + // SDA went high == stop command + elprintf(EL_EEPROM, "eeprom: -stop-"); + sreg &= ~8; + } + } + else if((sreg & 8) && !(sreg & 2) && (d&2)) + { + // we are started and SCL went high - next cycle + scyc++; // pre-increment + if(SRam.eeprom_type) { + // X24C02+ + if((ssa&1) && scyc == 18) { + scyc = 9; + saddr++; // next address in read mode + /*if(SRam.eeprom_type==2) saddr&=0xff; else*/ saddr&=0x1fff; // mask + } + else if(SRam.eeprom_type == 2 && scyc == 27) scyc = 18; + else if(scyc == 36) scyc = 27; + } else { + // X24C01 + if(scyc == 18) { + scyc = 9; // wrap + if(saddr&1) { saddr+=2; saddr&=0xff; } // next addr in read mode + } + } + elprintf(EL_EEPROM, "eeprom: scyc: %i", scyc); + } + else if((sreg & 8) && (sreg & 2) && !(d&2)) + { + // we are started and SCL went low (falling edge) + if(SRam.eeprom_type) { + // X24C02+ + if(scyc == 9 || scyc == 18 || scyc == 27); // ACK cycles + else if( (SRam.eeprom_type == 3 && scyc > 27) || (SRam.eeprom_type == 2 && scyc > 18) ) { + if(!(ssa&1)) { + // data write + unsigned char *pm=SRam.data+saddr; + *pm <<= 1; *pm |= d&1; + if(scyc == 26 || scyc == 35) { + saddr=(saddr&~0xf)|((saddr+1)&0xf); // only 4 (?) lowest bits are incremented + elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr, *pm); + } + SRam.changed = 1; + } + } else if(scyc > 9) { + if(!(ssa&1)) { + // we latch another addr bit + saddr<<=1; + if(SRam.eeprom_type == 2) saddr&=0xff; else saddr&=0x1fff; // mask + saddr|=d&1; + if(scyc==17||scyc==26) { + elprintf(EL_EEPROM, "eeprom: addr reg done: %x", saddr); + if(scyc==17&&SRam.eeprom_type==2) { saddr&=0xff; saddr|=(ssa<<7)&0x700; } // add device bits too + } + } + } else { + // slave address + ssa<<=1; ssa|=d&1; + if(scyc==8) elprintf(EL_EEPROM, "eeprom: slave done: %x", ssa); + } + } else { + // X24C01 + if(scyc == 9); // ACK cycle, do nothing + else if(scyc > 9) { + if(!(saddr&1)) { + // data write + unsigned char *pm=SRam.data+(saddr>>1); + *pm <<= 1; *pm |= d&1; + if(scyc == 17) { + saddr=(saddr&0xf9)|((saddr+2)&6); // only 2 lowest bits are incremented + elprintf(EL_EEPROM, "eeprom: write done, addr inc to: %x, last byte=%02x", saddr>>1, *pm); + } + SRam.changed = 1; + } + } else { + // we latch another addr bit + saddr<<=1; saddr|=d&1; saddr&=0xff; + if(scyc==8) elprintf(EL_EEPROM, "eeprom: addr done: %x", saddr>>1); + } + } + } + + sreg &= ~3; sreg |= d&3; // remember SCL and SDA + Pico.m.eeprom_status = (unsigned char) sreg; + Pico.m.eeprom_cycle = (unsigned char) scyc; + Pico.m.eeprom_slave = (unsigned char) ssa; + Pico.m.eeprom_addr = (unsigned short)saddr; +} + +static void EEPROM_upd_pending(unsigned int d) +{ + unsigned int d1, sreg = Pico.m.eeprom_status; + + sreg &= ~0xc0; + + // SCL + d1 = (d >> SRam.eeprom_bit_cl) & 1; + sreg |= d1 << 7; + + // SDA in + d1 = (d >> SRam.eeprom_bit_in) & 1; + sreg |= d1 << 6; + + Pico.m.eeprom_status = (unsigned char) sreg; +} + +void EEPROM_write16(unsigned int d) +{ + // this diff must be at most 16 for NBA Jam to work + if (SekCyclesDone() - last_write < 16) { + // just update pending state + elprintf(EL_EEPROM, "eeprom: skip because cycles=%i", + SekCyclesDone() - last_write); + EEPROM_upd_pending(d); + } else { + int srs = Pico.m.eeprom_status; + EEPROM_write_do(srs >> 6); // execute pending + EEPROM_upd_pending(d); + if ((srs ^ Pico.m.eeprom_status) & 0xc0) // update time only if SDA/SCL changed + last_write = SekCyclesDone(); + } +} + +void EEPROM_write8(unsigned int a, unsigned int d) +{ + unsigned char *wb = Pico.m.eeprom_wb; + wb[a & 1] = d; + EEPROM_write16((wb[0] << 8) | wb[1]); +} + +unsigned int EEPROM_read(void) +{ + unsigned int shift, d; + unsigned int sreg, saddr, scyc, ssa, interval; + + // flush last pending write + EEPROM_write_do(Pico.m.eeprom_status>>6); + + sreg = Pico.m.eeprom_status; saddr = Pico.m.eeprom_addr&0x1fff; scyc = Pico.m.eeprom_cycle; ssa = Pico.m.eeprom_slave; + interval = SekCyclesDone() - last_write; + d = (sreg>>6)&1; // use SDA as "open bus" + + // NBA Jam is nasty enough to read raising the SCL and starting the new cycle. + // this is probably valid because data changes occur while SCL is low and data can be read + // before it's actual cycle begins. + if (!(sreg&0x80) && interval >= 24) { + elprintf(EL_EEPROM, "eeprom: early read, cycles=%i", interval); + scyc++; + } + + if (!(sreg & 8)); // not started, use open bus + else if (scyc == 9 || scyc == 18 || scyc == 27) { + elprintf(EL_EEPROM, "eeprom: r ack"); + d = 0; + } else if (scyc > 9 && scyc < 18) { + // started and first command word received + shift = 17-scyc; + if (SRam.eeprom_type) { + // X24C02+ + if (ssa&1) { + elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr, scyc, sreg); + if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr]); + d = (SRam.data[saddr]>>shift)&1; + } + } else { + // X24C01 + if (saddr&1) { + elprintf(EL_EEPROM, "eeprom: read: addr %02x, cycle %i, reg %02x", saddr>>1, scyc, sreg); + if (shift==0) elprintf(EL_EEPROM, "eeprom: read done, byte %02x", SRam.data[saddr>>1]); + d = (SRam.data[saddr>>1]>>shift)&1; + } + } + } + + return (d << SRam.eeprom_bit_out); +} + diff --git a/waterbox/picodrive/pico/media.c b/waterbox/picodrive/pico/media.c new file mode 100644 index 0000000000..4f22a0c98a --- /dev/null +++ b/waterbox/picodrive/pico/media.c @@ -0,0 +1,161 @@ +/* + * PicoDrive + * (C) notaz, 2006-2010,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include +#include "pico_int.h" +#include "cd/cue.h" + +unsigned char media_id_header[0x100]; + +static void strlwr_(char *string) +{ + char *p; + for (p = string; *p; p++) + if ('A' <= *p && *p <= 'Z') + *p += 'a' - 'A'; +} + +static void get_ext(const char *file, char *ext) +{ + const char *p; + + p = file + strlen(file) - 4; + if (p < file) + p = file; + strncpy(ext, p, 4); + ext[4] = 0; + strlwr_(ext); +} + +enum media_type_e PicoLoadMedia( + const char *filename, + const char *carthw_cfg_fname, + const char *(*get_bios_filename)(int *region, const char *cd_fname), + void (*do_region_override)(const char *media_filename), enum media_type_e media_type) +{ + const char *rom_fname = filename; + enum cd_img_type cd_img_type = CIT_NOT_CD; + unsigned char *rom_data = NULL; + unsigned int rom_size = 0; + pm_file *rom = NULL; + int cd_region = 0; + int ret; + + if (media_type == PM_BAD_DETECT) + goto out; + + PicoAHW = 0; + PicoQuirks = 0; + + if (media_type == PM_CD) + { + // check for MegaCD image + cd_img_type = PicoCdCheck(filename, &cd_region); + if ((int)cd_img_type >= 0 && cd_img_type != CIT_NOT_CD) + { + // valid CD image, ask frontend for BIOS.. + rom_fname = NULL; + if (get_bios_filename != NULL) + rom_fname = get_bios_filename(&cd_region, filename); + if (rom_fname == NULL) + { + media_type = PM_BAD_CD_NO_BIOS; + goto out; + } + + PicoAHW |= PAHW_MCD; + } + else + { + media_type = PM_BAD_CD; + goto out; + } + } + else if (media_type == PM_MARK3) + { + lprintf("detected SMS ROM\n"); + PicoAHW = PAHW_SMS; + } + + rom = pm_open(rom_fname); + if (rom == NULL) + { + lprintf("Failed to open ROM"); + media_type = PM_ERROR; + goto out; + } + + ret = PicoCartLoad(rom, &rom_data, &rom_size, (PicoAHW & PAHW_SMS) ? 1 : 0); + pm_close(rom); + if (ret != 0) + { + if (ret == 2) + lprintf("Out of memory"); + else if (ret == 3) + lprintf("Read failed"); + else + lprintf("PicoCartLoad() failed."); + media_type = PM_ERROR; + goto out; + } + + // detect wrong files + if (strncmp((char *)rom_data, "Pico", 4) == 0) + { + lprintf("savestate selected?\n"); + media_type = PM_BAD_DETECT; + goto out; + } + + if (!(PicoAHW & PAHW_SMS)) + { + unsigned short *d = (unsigned short *)(rom_data + 4); + if ((((d[0] << 16) | d[1]) & 0xffffff) >= (int)rom_size) + { + lprintf("bad reset vector\n"); + media_type = PM_BAD_DETECT; + goto out; + } + } + + // load config for this ROM (do this before insert to get correct region) + if (!(PicoAHW & PAHW_MCD)) + { + memcpy(media_id_header, rom_data + 0x100, sizeof(media_id_header)); + if (do_region_override != NULL) + do_region_override(filename); + } + + if (PicoCartInsert(rom_data, rom_size, carthw_cfg_fname)) + { + media_type = PM_ERROR; + goto out; + } + rom_data = NULL; // now belongs to PicoCart + Pico.m.ncart_in = 0; + + // insert CD if it was detected + if (cd_img_type != CIT_NOT_CD) + { + ret = cdd_load(filename, cd_img_type); + if (ret != 0) + { + media_type = PM_BAD_CD; + goto out; + } + Pico.m.ncart_in = 1; + } + + if (PicoQuirks & PQUIRK_FORCE_6BTN) + PicoSetInputDevice(0, PICO_INPUT_PAD_6BTN); + +out: + if (rom_data) + free(rom_data); + return media_type; +} diff --git a/waterbox/picodrive/pico/memory.c b/waterbox/picodrive/pico/memory.c new file mode 100644 index 0000000000..4f38e5e2a3 --- /dev/null +++ b/waterbox/picodrive/pico/memory.c @@ -0,0 +1,1241 @@ +/* + * memory handling + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" +#include "memory.h" + +#include "sound/ym2612.h" +#include "sound/sn76496.h" + +extern unsigned int lastSSRamWrite; // used by serial eeprom code + +uptr m68k_read8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_read16_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_write8_map [0x1000000 >> M68K_MEM_SHIFT]; +uptr m68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; + +static void xmap_set(uptr *map, int shift, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ +#ifdef __clang__ + // workaround bug (segfault) in + // Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) + volatile +#endif + uptr addr = (uptr)func_or_mh; + int mask = (1 << shift) - 1; + int i; + + if ((start_addr & mask) != 0 || (end_addr & mask) != mask) { + elprintf(EL_STATUS|EL_ANOMALY, "xmap_set: tried to map bad range: %06x-%06x", + start_addr, end_addr); + return; + } + + if (addr & 1) { + elprintf(EL_STATUS|EL_ANOMALY, "xmap_set: ptr is not aligned: %08lx", addr); + return; + } + + if (!is_func) + addr -= start_addr; + + for (i = start_addr >> shift; i <= end_addr >> shift; i++) { + map[i] = addr >> 1; + if (is_func) + map[i] |= MAP_FLAG; + } +} + +void z80_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ + xmap_set(map, Z80_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func); +} + +void cpu68k_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func) +{ + xmap_set(map, M68K_MEM_SHIFT, start_addr, end_addr, func_or_mh, is_func); +} + +// more specialized/optimized function (does same as above) +void cpu68k_map_all_ram(int start_addr, int end_addr, void *ptr, int is_sub) +{ + uptr *r8map, *r16map, *w8map, *w16map; + uptr addr = (uptr)ptr; + int shift = M68K_MEM_SHIFT; + int i; + + if (!is_sub) { + r8map = m68k_read8_map; + r16map = m68k_read16_map; + w8map = m68k_write8_map; + w16map = m68k_write16_map; + } else { + r8map = s68k_read8_map; + r16map = s68k_read16_map; + w8map = s68k_write8_map; + w16map = s68k_write16_map; + } + + addr -= start_addr; + addr >>= 1; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + r8map[i] = r16map[i] = w8map[i] = w16map[i] = addr; +} + +static u32 m68k_unmapped_read8(u32 a) +{ + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return 0; // assume pulldown, as if MegaCD2 was attached +} + +static u32 m68k_unmapped_read16(u32 a) +{ + elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + return 0; +} + +static void m68k_unmapped_write8(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); +} + +static void m68k_unmapped_write16(u32 a, u32 d) +{ + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + +void m68k_map_unmap(int start_addr, int end_addr) +{ +#ifdef __clang__ + // workaround bug (segfault) in + // Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn) + volatile +#endif + uptr addr; + int shift = M68K_MEM_SHIFT; + int i; + + addr = (uptr)m68k_unmapped_read8; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_read8_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_read16; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_read16_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_write8; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_write8_map[i] = (addr >> 1) | MAP_FLAG; + + addr = (uptr)m68k_unmapped_write16; + for (i = start_addr >> shift; i <= end_addr >> shift; i++) + m68k_write16_map[i] = (addr >> 1) | MAP_FLAG; +} + +MAKE_68K_READ8(m68k_read8, m68k_read8_map) +MAKE_68K_READ16(m68k_read16, m68k_read16_map) +MAKE_68K_READ32(m68k_read32, m68k_read16_map) +MAKE_68K_WRITE8(m68k_write8, m68k_write8_map) +MAKE_68K_WRITE16(m68k_write16, m68k_write16_map) +MAKE_68K_WRITE32(m68k_write32, m68k_write16_map) + +// ----------------------------------------------------------------- + +static u32 ym2612_read_local_68k(void); +static int ym2612_write_local(u32 a, u32 d, int is_from_z80); +static void z80_mem_setup(void); + +#ifdef _ASM_MEMORY_C +u32 PicoRead8_sram(u32 a); +u32 PicoRead16_sram(u32 a); +#endif + +#ifdef EMU_CORE_DEBUG +u32 lastread_a, lastread_d[16]={0,}, lastwrite_cyc_d[16]={0,}, lastwrite_mus_d[16]={0,}; +int lrp_cyc=0, lrp_mus=0, lwp_cyc=0, lwp_mus=0; +extern unsigned int ppop; +#endif + +#ifdef IO_STATS +void log_io(unsigned int addr, int bits, int rw); +#elif defined(_MSC_VER) +#define log_io +#else +#define log_io(...) +#endif + +#if defined(EMU_C68K) +void cyclone_crashed(u32 pc, struct Cyclone *context) +{ + elprintf(EL_STATUS|EL_ANOMALY, "%c68k crash detected @ %06x", + context == &PicoCpuCM68k ? 'm' : 's', pc); + context->membase = (u32)Pico.rom; + context->pc = (u32)Pico.rom + Pico.romsize; +} +#endif + +// ----------------------------------------------------------------- +// memmap helpers + +static u32 read_pad_3btn(int i, u32 out_bits) +{ + u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU + u32 value; + + if (out_bits & 0x40) // TH + value = pad & 0x3f; // ?1CB RLDU + else + value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU + + value |= out_bits & 0x40; + return value; +} + +static u32 read_pad_6btn(int i, u32 out_bits) +{ + u32 pad = ~PicoPadInt[i]; // Get inverse of pad MXYZ SACB RLDU + int phase = Pico.m.padTHPhase[i]; + u32 value; + + if (phase == 2 && !(out_bits & 0x40)) { + value = (pad & 0xc0) >> 2; // ?0SA 0000 + goto out; + } + else if(phase == 3) { + if (out_bits & 0x40) + return (pad & 0x30) | ((pad >> 8) & 0xf); // ?1CB MXYZ + else + return ((pad & 0xc0) >> 2) | 0x0f; // ?0SA 1111 + goto out; + } + + if (out_bits & 0x40) // TH + value = pad & 0x3f; // ?1CB RLDU + else + value = ((pad & 0xc0) >> 2) | (pad & 3); // ?0SA 00DU + +out: + value |= out_bits & 0x40; + return value; +} + +static u32 read_nothing(int i, u32 out_bits) +{ + return 0xff; +} + +typedef u32 (port_read_func)(int index, u32 out_bits); + +static port_read_func *port_readers[3] = { + read_pad_3btn, + read_pad_3btn, + read_nothing +}; + +static NOINLINE u32 port_read(int i) +{ + u32 data_reg = Pico.ioports[i + 1]; + u32 ctrl_reg = Pico.ioports[i + 4] | 0x80; + u32 in, out; + + out = data_reg & ctrl_reg; + out |= 0x7f & ~ctrl_reg; // pull-ups + + in = port_readers[i](i, out); + + return (in & ~ctrl_reg) | (data_reg & ctrl_reg); +} + +void PicoSetInputDevice(int port, enum input_device device) +{ + port_read_func *func; + + if (port < 0 || port > 2) + return; + + switch (device) { + case PICO_INPUT_PAD_3BTN: + func = read_pad_3btn; + break; + + case PICO_INPUT_PAD_6BTN: + func = read_pad_6btn; + break; + + default: + func = read_nothing; + break; + } + + port_readers[port] = func; +} + +NOINLINE u32 io_ports_read(u32 a) +{ + u32 d; + a = (a>>1) & 0xf; + switch (a) { + case 0: d = Pico.m.hardware; break; // Hardware value (Version register) + case 1: d = port_read(0); break; + case 2: d = port_read(1); break; + case 3: d = port_read(2); break; + default: d = Pico.ioports[a]; break; // IO ports can be used as RAM + } + return d; +} + +NOINLINE void io_ports_write(u32 a, u32 d) +{ + a = (a>>1) & 0xf; + + // 6 button gamepad: if TH went from 0 to 1, gamepad changes state + if (1 <= a && a <= 2) + { + Pico.m.padDelay[a - 1] = 0; + if (!(Pico.ioports[a] & 0x40) && (d & 0x40)) + Pico.m.padTHPhase[a - 1]++; + } + + // certain IO ports can be used as RAM + Pico.ioports[a] = d; +} + +// lame.. +static int z80_cycles_from_68k(void) +{ + return z80_cycle_aim + + cycles_68k_to_z80(SekCyclesDone() - last_z80_sync); +} + +void NOINLINE ctl_write_z80busreq(u32 d) +{ + d&=1; d^=1; + elprintf(EL_BUSREQ, "set_zrun: %i->%i [%i] @%06x", Pico.m.z80Run, d, SekCyclesDone(), SekPc); + if (d ^ Pico.m.z80Run) + { + if (d) + { + z80_cycle_cnt = z80_cycles_from_68k(); + } + else + { + if ((PicoOpt&POPT_EN_Z80) && !Pico.m.z80_reset) { + pprof_start(m68k); + PicoSyncZ80(SekCyclesDone()); + pprof_end_sub(m68k); + } + } + Pico.m.z80Run = d; + } +} + +void NOINLINE ctl_write_z80reset(u32 d) +{ + d&=1; d^=1; + elprintf(EL_BUSREQ, "set_zreset: %i->%i [%i] @%06x", Pico.m.z80_reset, d, SekCyclesDone(), SekPc); + if (d ^ Pico.m.z80_reset) + { + if (d) + { + if ((PicoOpt&POPT_EN_Z80) && Pico.m.z80Run) { + pprof_start(m68k); + PicoSyncZ80(SekCyclesDone()); + pprof_end_sub(m68k); + } + YM2612ResetChip(); + timers_reset(); + } + else + { + z80_cycle_cnt = z80_cycles_from_68k(); + z80_reset(); + } + Pico.m.z80_reset = d; + } +} + +// ----------------------------------------------------------------- + +#ifndef _ASM_MEMORY_C + +// cart (save) RAM area (usually 0x200000 - ...) +static u32 PicoRead8_sram(u32 a) +{ + u32 d; + if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + { + if (SRam.flags & SRF_EEPROM) { + d = EEPROM_read(); + if (!(a & 1)) + d >>= 8; + } else + d = *(u8 *)(SRam.data - SRam.start + a); + elprintf(EL_SRAMIO, "sram r8 [%06x] %02x @ %06x", a, d, SekPc); + return d; + } + + // XXX: this is banking unfriendly + if (a < Pico.romsize) + return Pico.rom[a ^ 1]; + + return m68k_unmapped_read8(a); +} + +static u32 PicoRead16_sram(u32 a) +{ + u32 d; + if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED)) + { + if (SRam.flags & SRF_EEPROM) + d = EEPROM_read(); + else { + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + d = pm[0] << 8; + d |= pm[1]; + } + elprintf(EL_SRAMIO, "sram r16 [%06x] %04x @ %06x", a, d, SekPc); + return d; + } + + if (a < Pico.romsize) + return *(u16 *)(Pico.rom + a); + + return m68k_unmapped_read16(a); +} + +#endif // _ASM_MEMORY_C + +static void PicoWrite8_sram(u32 a, u32 d) +{ + if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + m68k_unmapped_write8(a, d); + return; + } + + elprintf(EL_SRAMIO, "sram w8 [%06x] %02x @ %06x", a, d & 0xff, SekPc); + if (SRam.flags & SRF_EEPROM) + { + EEPROM_write8(a, d); + } + else { + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + if (*pm != (u8)d) { + SRam.changed = 1; + *pm = (u8)d; + } + } +} + +static void PicoWrite16_sram(u32 a, u32 d) +{ + if (a > SRam.end || a < SRam.start || !(Pico.m.sram_reg & SRR_MAPPED)) { + m68k_unmapped_write16(a, d); + return; + } + + elprintf(EL_SRAMIO, "sram w16 [%06x] %04x @ %06x", a, d & 0xffff, SekPc); + if (SRam.flags & SRF_EEPROM) + { + EEPROM_write16(d); + } + else { + // XXX: hardware could easily use MSB too.. + u8 *pm = (u8 *)(SRam.data - SRam.start + a); + if (*pm != (u8)d) { + SRam.changed = 1; + *pm = (u8)d; + } + } +} + +// z80 area (0xa00000 - 0xa0ffff) +// TODO: verify mirrors VDP and bank reg (bank area mirroring verified) +static u32 PicoRead8_z80(u32 a) +{ + u32 d = 0xff; + if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + elprintf(EL_ANOMALY, "68k z80 read with no bus! [%06x] @ %06x", a, SekPc); + // open bus. Pulled down if MegaCD2 is attached. + return 0; + } + + if ((a & 0x4000) == 0x0000) + d = Pico.zram[a & 0x1fff]; + else if ((a & 0x6000) == 0x4000) // 0x4000-0x5fff + d = ym2612_read_local_68k(); + else + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return d; +} + +static u32 PicoRead16_z80(u32 a) +{ + u32 d = PicoRead8_z80(a); + return d | (d << 8); +} + +static void PicoWrite8_z80(u32 a, u32 d) +{ + if ((Pico.m.z80Run & 1) || Pico.m.z80_reset) { + // verified on real hw + elprintf(EL_ANOMALY, "68k z80 write with no bus or reset! [%06x] %02x @ %06x", a, d&0xff, SekPc); + return; + } + + if ((a & 0x4000) == 0x0000) { // z80 RAM + SekCyclesBurnRun(2); // FIXME hack + Pico.zram[a & 0x1fff] = (u8)d; + return; + } + if ((a & 0x6000) == 0x4000) { // FM Sound + if (PicoOpt & POPT_EN_FM) + emustatus |= ym2612_write_local(a&3, d&0xff, 0)&1; + return; + } + // TODO: probably other VDP access too? Maybe more mirrors? + if ((a & 0x7ff9) == 0x7f11) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + return; + } + if ((a & 0x7f00) == 0x6000) // Z80 BANK register + { + Pico.m.z80_bank68k >>= 1; + Pico.m.z80_bank68k |= d << 8; + Pico.m.z80_bank68k &= 0x1ff; // 9 bits and filled in the new top one + elprintf(EL_Z80BNK, "z80 bank=%06x", Pico.m.z80_bank68k << 15); + return; + } + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %02x @ %06x", a, d&0xff, SekPc); +} + +static void PicoWrite16_z80(u32 a, u32 d) +{ + // for RAM, only most significant byte is sent + // TODO: verify remaining accesses + PicoWrite8_z80(a, d >> 8); +} + +#ifndef _ASM_MEMORY_C + +// IO/control area (0xa10000 - 0xa1ffff) +u32 PicoRead8_io(u32 a) +{ + u32 d; + + if ((a & 0xffe0) == 0x0000) { // I/O ports + d = io_ports_read(a); + goto end; + } + + // faking open bus (MegaCD pulldowns don't work here curiously) + d = Pico.m.rotate++; + d ^= d << 6; + + if ((a & 0xfc00) == 0x1000) { + // bit8 seems to be readable in this range + if (!(a & 1)) + d &= ~0x01; + + if ((a & 0xff01) == 0x1100) { // z80 busreq (verified) + d |= (Pico.m.z80Run | Pico.m.z80_reset) & 1; + elprintf(EL_BUSREQ, "get_zrun: %02x [%i] @%06x", d, SekCyclesDone(), SekPc); + } + goto end; + } + + if (PicoOpt & POPT_EN_32X) { + d = PicoRead8_32x(a); + goto end; + } + + d = m68k_unmapped_read8(a); +end: + return d; +} + +u32 PicoRead16_io(u32 a) +{ + u32 d; + + if ((a & 0xffe0) == 0x0000) { // I/O ports + d = io_ports_read(a); + d |= d << 8; + goto end; + } + + // faking open bus + d = (Pico.m.rotate += 0x41); + d ^= (d << 5) ^ (d << 8); + + // bit8 seems to be readable in this range + if ((a & 0xfc00) == 0x1000) { + d &= ~0x0100; + + if ((a & 0xff00) == 0x1100) { // z80 busreq + d |= ((Pico.m.z80Run | Pico.m.z80_reset) & 1) << 8; + elprintf(EL_BUSREQ, "get_zrun: %04x [%i] @%06x", d, SekCyclesDone(), SekPc); + } + goto end; + } + + if (PicoOpt & POPT_EN_32X) { + d = PicoRead16_32x(a); + goto end; + } + + d = m68k_unmapped_read16(a); +end: + return d; +} + +void PicoWrite8_io(u32 a, u32 d) +{ + if ((a & 0xffe1) == 0x0001) { // I/O ports (verified: only LSB!) + io_ports_write(a, d); + return; + } + if ((a & 0xff01) == 0x1100) { // z80 busreq + ctl_write_z80busreq(d); + return; + } + if ((a & 0xff01) == 0x1200) { // z80 reset + ctl_write_z80reset(d); + return; + } + if (a == 0xa130f1) { // sram access register + elprintf(EL_SRAMIO, "sram reg=%02x", d); + Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY); + Pico.m.sram_reg |= (u8)(d & 3); + return; + } + if (PicoOpt & POPT_EN_32X) { + PicoWrite8_32x(a, d); + return; + } + + m68k_unmapped_write8(a, d); +} + +void PicoWrite16_io(u32 a, u32 d) +{ + if ((a & 0xffe0) == 0x0000) { // I/O ports (verified: only LSB!) + io_ports_write(a, d); + return; + } + if ((a & 0xff00) == 0x1100) { // z80 busreq + ctl_write_z80busreq(d >> 8); + return; + } + if ((a & 0xff00) == 0x1200) { // z80 reset + ctl_write_z80reset(d >> 8); + return; + } + if (a == 0xa130f0) { // sram access register + elprintf(EL_SRAMIO, "sram reg=%02x", d); + Pico.m.sram_reg &= ~(SRR_MAPPED|SRR_READONLY); + Pico.m.sram_reg |= (u8)(d & 3); + return; + } + if (PicoOpt & POPT_EN_32X) { + PicoWrite16_32x(a, d); + return; + } + m68k_unmapped_write16(a, d); +} + +#endif // _ASM_MEMORY_C + +// VDP area (0xc00000 - 0xdfffff) +// TODO: verify if lower byte goes to PSG on word writes +static u32 PicoRead8_vdp(u32 a) +{ + if ((a & 0x00e0) == 0x0000) + return PicoVideoRead8(a); + + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return 0; +} + +static u32 PicoRead16_vdp(u32 a) +{ + if ((a & 0x00e0) == 0x0000) + return PicoVideoRead(a); + + elprintf(EL_UIO|EL_ANOMALY, "68k bad read [%06x] @%06x", a, SekPc); + return 0; +} + +static void PicoWrite8_vdp(u32 a, u32 d) +{ + if ((a & 0x00f9) == 0x0011) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + return; + } + if ((a & 0x00e0) == 0x0000) { + d &= 0xff; + PicoVideoWrite(a, d | (d << 8)); + return; + } + + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %02x @%06x", a, d & 0xff, SekPc); +} + +static void PicoWrite16_vdp(u32 a, u32 d) +{ + if ((a & 0x00f9) == 0x0010) { // PSG Sound + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + return; + } + if ((a & 0x00e0) == 0x0000) { + PicoVideoWrite(a, d); + return; + } + + elprintf(EL_UIO|EL_ANOMALY, "68k bad write [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + +// ----------------------------------------------------------------- + +#ifdef EMU_M68K +static void m68k_mem_setup(void); +#endif + +PICO_INTERNAL void PicoMemSetup(void) +{ + int mask, rs, a; + + // setup the memory map + cpu68k_map_set(m68k_read8_map, 0x000000, 0xffffff, m68k_unmapped_read8, 1); + cpu68k_map_set(m68k_read16_map, 0x000000, 0xffffff, m68k_unmapped_read16, 1); + cpu68k_map_set(m68k_write8_map, 0x000000, 0xffffff, m68k_unmapped_write8, 1); + cpu68k_map_set(m68k_write16_map, 0x000000, 0xffffff, m68k_unmapped_write16, 1); + + // ROM + // align to bank size. We know ROM loader allocated enough for this + mask = (1 << M68K_MEM_SHIFT) - 1; + rs = (Pico.romsize + mask) & ~mask; + cpu68k_map_set(m68k_read8_map, 0x000000, rs - 1, Pico.rom, 0); + cpu68k_map_set(m68k_read16_map, 0x000000, rs - 1, Pico.rom, 0); + + // Common case of on-cart (save) RAM, usually at 0x200000-... + if ((SRam.flags & SRF_ENABLED) && SRam.data != NULL) { + rs = SRam.end - SRam.start; + rs = (rs + mask) & ~mask; + if (SRam.start + rs >= 0x1000000) + rs = 0x1000000 - SRam.start; + cpu68k_map_set(m68k_read8_map, SRam.start, SRam.start + rs - 1, PicoRead8_sram, 1); + cpu68k_map_set(m68k_read16_map, SRam.start, SRam.start + rs - 1, PicoRead16_sram, 1); + cpu68k_map_set(m68k_write8_map, SRam.start, SRam.start + rs - 1, PicoWrite8_sram, 1); + cpu68k_map_set(m68k_write16_map, SRam.start, SRam.start + rs - 1, PicoWrite16_sram, 1); + } + + // Z80 region + cpu68k_map_set(m68k_read8_map, 0xa00000, 0xa0ffff, PicoRead8_z80, 1); + cpu68k_map_set(m68k_read16_map, 0xa00000, 0xa0ffff, PicoRead16_z80, 1); + cpu68k_map_set(m68k_write8_map, 0xa00000, 0xa0ffff, PicoWrite8_z80, 1); + cpu68k_map_set(m68k_write16_map, 0xa00000, 0xa0ffff, PicoWrite16_z80, 1); + + // IO/control region + cpu68k_map_set(m68k_read8_map, 0xa10000, 0xa1ffff, PicoRead8_io, 1); + cpu68k_map_set(m68k_read16_map, 0xa10000, 0xa1ffff, PicoRead16_io, 1); + cpu68k_map_set(m68k_write8_map, 0xa10000, 0xa1ffff, PicoWrite8_io, 1); + cpu68k_map_set(m68k_write16_map, 0xa10000, 0xa1ffff, PicoWrite16_io, 1); + + // VDP region + for (a = 0xc00000; a < 0xe00000; a += 0x010000) { + if ((a & 0xe700e0) != 0xc00000) + continue; + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, PicoRead8_vdp, 1); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, PicoRead16_vdp, 1); + cpu68k_map_set(m68k_write8_map, a, a + 0xffff, PicoWrite8_vdp, 1); + cpu68k_map_set(m68k_write16_map, a, a + 0xffff, PicoWrite16_vdp, 1); + } + + // RAM and it's mirrors + for (a = 0xe00000; a < 0x1000000; a += 0x010000) { + cpu68k_map_set(m68k_read8_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_read16_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_write8_map, a, a + 0xffff, Pico.ram, 0); + cpu68k_map_set(m68k_write16_map, a, a + 0xffff, Pico.ram, 0); + } + + // Setup memory callbacks: +#ifdef EMU_C68K + PicoCpuCM68k.read8 = (void *)m68k_read8_map; + PicoCpuCM68k.read16 = (void *)m68k_read16_map; + PicoCpuCM68k.read32 = (void *)m68k_read16_map; + PicoCpuCM68k.write8 = (void *)m68k_write8_map; + PicoCpuCM68k.write16 = (void *)m68k_write16_map; + PicoCpuCM68k.write32 = (void *)m68k_write16_map; + PicoCpuCM68k.checkpc = NULL; /* unused */ + PicoCpuCM68k.fetch8 = NULL; + PicoCpuCM68k.fetch16 = NULL; + PicoCpuCM68k.fetch32 = NULL; +#endif +#ifdef EMU_F68K + PicoCpuFM68k.read_byte = m68k_read8; + PicoCpuFM68k.read_word = m68k_read16; + PicoCpuFM68k.read_long = m68k_read32; + PicoCpuFM68k.write_byte = m68k_write8; + PicoCpuFM68k.write_word = m68k_write16; + PicoCpuFM68k.write_long = m68k_write32; + + // setup FAME fetchmap + { + int i; + // by default, point everything to first 64k of ROM + for (i = 0; i < M68K_FETCHBANK1; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom - (i<<(24-FAMEC_FETCHBITS)); + // now real ROM + for (i = 0; i < M68K_FETCHBANK1 && (i<<(24-FAMEC_FETCHBITS)) < Pico.romsize; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.rom; + // .. and RAM + for (i = M68K_FETCHBANK1*14/16; i < M68K_FETCHBANK1; i++) + PicoCpuFM68k.Fetch[i] = (unsigned long)Pico.ram - (i<<(24-FAMEC_FETCHBITS)); + } +#endif +#ifdef EMU_M68K + m68k_mem_setup(); +#endif + + z80_mem_setup(); +} + +#ifdef EMU_M68K +unsigned int (*pm68k_read_memory_8) (unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_16)(unsigned int address) = NULL; +unsigned int (*pm68k_read_memory_32)(unsigned int address) = NULL; +void (*pm68k_write_memory_8) (unsigned int address, unsigned char value) = NULL; +void (*pm68k_write_memory_16)(unsigned int address, unsigned short value) = NULL; +void (*pm68k_write_memory_32)(unsigned int address, unsigned int value) = NULL; + +/* it appears that Musashi doesn't always mask the unused bits */ +unsigned int m68k_read_memory_8 (unsigned int address) { return pm68k_read_memory_8 (address) & 0xff; } +unsigned int m68k_read_memory_16(unsigned int address) { return pm68k_read_memory_16(address) & 0xffff; } +unsigned int m68k_read_memory_32(unsigned int address) { return pm68k_read_memory_32(address); } +void m68k_write_memory_8 (unsigned int address, unsigned int value) { pm68k_write_memory_8 (address, (u8)value); } +void m68k_write_memory_16(unsigned int address, unsigned int value) { pm68k_write_memory_16(address,(u16)value); } +void m68k_write_memory_32(unsigned int address, unsigned int value) { pm68k_write_memory_32(address, value); } + +static void m68k_mem_setup(void) +{ + pm68k_read_memory_8 = m68k_read8; + pm68k_read_memory_16 = m68k_read16; + pm68k_read_memory_32 = m68k_read32; + pm68k_write_memory_8 = m68k_write8; + pm68k_write_memory_16 = m68k_write16; + pm68k_write_memory_32 = m68k_write32; +} +#endif // EMU_M68K + + +// ----------------------------------------------------------------- + +static int get_scanline(int is_from_z80) +{ + if (is_from_z80) { + int cycles = z80_cyclesDone(); + while (cycles - z80_scanline_cycles >= 228) + z80_scanline++, z80_scanline_cycles += 228; + return z80_scanline; + } + + return Pico.m.scanline; +} + +/* probably should not be in this file, but it's near related code here */ +void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new) +{ + int xcycles = z80_cycles << 8; + + /* check for overflows */ + if ((mode_old & 4) && xcycles > timer_a_next_oflow) + ym2612.OPN.ST.status |= 1; + + if ((mode_old & 8) && xcycles > timer_b_next_oflow) + ym2612.OPN.ST.status |= 2; + + /* update timer a */ + if (mode_old & 1) + while (xcycles > timer_a_next_oflow) + timer_a_next_oflow += timer_a_step; + + if ((mode_old ^ mode_new) & 1) // turning on/off + { + if (mode_old & 1) + timer_a_next_oflow = TIMER_NO_OFLOW; + else + timer_a_next_oflow = xcycles + timer_a_step; + } + if (mode_new & 1) + elprintf(EL_YMTIMER, "timer a upd to %i @ %i", timer_a_next_oflow>>8, z80_cycles); + + /* update timer b */ + if (mode_old & 2) + while (xcycles > timer_b_next_oflow) + timer_b_next_oflow += timer_b_step; + + if ((mode_old ^ mode_new) & 2) + { + if (mode_old & 2) + timer_b_next_oflow = TIMER_NO_OFLOW; + else + timer_b_next_oflow = xcycles + timer_b_step; + } + if (mode_new & 2) + elprintf(EL_YMTIMER, "timer b upd to %i @ %i", timer_b_next_oflow>>8, z80_cycles); +} + +// ym2612 DAC and timer I/O handlers for z80 +static int ym2612_write_local(u32 a, u32 d, int is_from_z80) +{ + int addr; + + a &= 3; + if (a == 1 && ym2612.OPN.ST.address == 0x2a) /* DAC data */ + { + int scanline = get_scanline(is_from_z80); + //elprintf(EL_STATUS, "%03i -> %03i dac w %08x z80 %i", PsndDacLine, scanline, d, is_from_z80); + ym2612.dacout = ((int)d - 0x80) << 6; + if (PsndOut && ym2612.dacen && scanline >= PsndDacLine) + PsndDoDAC(scanline); + return 0; + } + + switch (a) + { + case 0: /* address port 0 */ + ym2612.OPN.ST.address = d; + ym2612.addr_A1 = 0; +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1); +#endif + return 0; + + case 1: /* data port 0 */ + if (ym2612.addr_A1 != 0) + return 0; + + addr = ym2612.OPN.ST.address; + ym2612.REGS[addr] = d; + + switch (addr) + { + case 0x24: // timer A High 8 + case 0x25: { // timer A Low 2 + int TAnew = (addr == 0x24) ? ((ym2612.OPN.ST.TA & 0x03)|(((int)d)<<2)) + : ((ym2612.OPN.ST.TA & 0x3fc)|(d&3)); + if (ym2612.OPN.ST.TA != TAnew) + { + //elprintf(EL_STATUS, "timer a set %i", TAnew); + ym2612.OPN.ST.TA = TAnew; + //ym2612.OPN.ST.TAC = (1024-TAnew)*18; + //ym2612.OPN.ST.TAT = 0; + timer_a_step = TIMER_A_TICK_ZCYCLES * (1024 - TAnew); + if (ym2612.OPN.ST.mode & 1) { + // this is not right, should really be done on overflow only + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); + timer_a_next_oflow = (cycles << 8) + timer_a_step; + } + elprintf(EL_YMTIMER, "timer a set to %i, %i", 1024 - TAnew, timer_a_next_oflow>>8); + } + return 0; + } + case 0x26: // timer B + if (ym2612.OPN.ST.TB != d) { + //elprintf(EL_STATUS, "timer b set %i", d); + ym2612.OPN.ST.TB = d; + //ym2612.OPN.ST.TBC = (256-d) * 288; + //ym2612.OPN.ST.TBT = 0; + timer_b_step = TIMER_B_TICK_ZCYCLES * (256 - d); // 262800 + if (ym2612.OPN.ST.mode & 2) { + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); + timer_b_next_oflow = (cycles << 8) + timer_b_step; + } + elprintf(EL_YMTIMER, "timer b set to %i, %i", 256 - d, timer_b_next_oflow>>8); + } + return 0; + case 0x27: { /* mode, timer control */ + int old_mode = ym2612.OPN.ST.mode; + int cycles = is_from_z80 ? z80_cyclesDone() : z80_cycles_from_68k(); + ym2612.OPN.ST.mode = d; + + elprintf(EL_YMTIMER, "st mode %02x", d); + ym2612_sync_timers(cycles, old_mode, d); + + /* reset Timer a flag */ + if (d & 0x10) + ym2612.OPN.ST.status &= ~1; + + /* reset Timer b flag */ + if (d & 0x20) + ym2612.OPN.ST.status &= ~2; + + if ((d ^ old_mode) & 0xc0) { +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) return YM2612Write_940(a, d, get_scanline(is_from_z80)); +#endif + return 1; + } + return 0; + } + case 0x2b: { /* DAC Sel (YM2612) */ + int scanline = get_scanline(is_from_z80); + ym2612.dacen = d & 0x80; + if (d & 0x80) PsndDacLine = scanline; +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, scanline); +#endif + return 0; + } + } + break; + + case 2: /* address port 1 */ + ym2612.OPN.ST.address = d; + ym2612.addr_A1 = 1; +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) YM2612Write_940(a, d, -1); +#endif + return 0; + + case 3: /* data port 1 */ + if (ym2612.addr_A1 != 1) + return 0; + + addr = ym2612.OPN.ST.address | 0x100; + ym2612.REGS[addr] = d; + break; + } + +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) + return YM2612Write_940(a, d, get_scanline(is_from_z80)); +#endif + return YM2612Write_(a, d); +} + + +#define ym2612_read_local() \ + if (xcycles >= timer_a_next_oflow) \ + ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 1; \ + if (xcycles >= timer_b_next_oflow) \ + ym2612.OPN.ST.status |= (ym2612.OPN.ST.mode >> 2) & 2 + +static u32 ym2612_read_local_z80(void) +{ + int xcycles = z80_cyclesDone() << 8; + + ym2612_read_local(); + + elprintf(EL_YMTIMER, "timer z80 read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, + timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); + return ym2612.OPN.ST.status; +} + +static u32 ym2612_read_local_68k(void) +{ + int xcycles = z80_cycles_from_68k() << 8; + + ym2612_read_local(); + + elprintf(EL_YMTIMER, "timer 68k read %i, sched %i, %i @ %i|%i", ym2612.OPN.ST.status, + timer_a_next_oflow>>8, timer_b_next_oflow>>8, xcycles >> 8, (xcycles >> 8) / 228); + return ym2612.OPN.ST.status; +} + +void ym2612_pack_state(void) +{ + // timers are saved as tick counts, in 16.16 int format + int tac, tat = 0, tbc, tbt = 0; + tac = 1024 - ym2612.OPN.ST.TA; + tbc = 256 - ym2612.OPN.ST.TB; + if (timer_a_next_oflow != TIMER_NO_OFLOW) + tat = (int)((double)(timer_a_step - timer_a_next_oflow) / (double)timer_a_step * tac * 65536); + if (timer_b_next_oflow != TIMER_NO_OFLOW) + tbt = (int)((double)(timer_b_step - timer_b_next_oflow) / (double)timer_b_step * tbc * 65536); + elprintf(EL_YMTIMER, "save: timer a %i/%i", tat >> 16, tac); + elprintf(EL_YMTIMER, "save: timer b %i/%i", tbt >> 16, tbc); + +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) + YM2612PicoStateSave2_940(tat, tbt); + else +#endif + YM2612PicoStateSave2(tat, tbt); +} + +void ym2612_unpack_state(void) +{ + int i, ret, tac, tat, tbc, tbt; + YM2612PicoStateLoad(); + + // feed all the registers and update internal state + for (i = 0x20; i < 0xA0; i++) { + ym2612_write_local(0, i, 0); + ym2612_write_local(1, ym2612.REGS[i], 0); + } + for (i = 0x30; i < 0xA0; i++) { + ym2612_write_local(2, i, 0); + ym2612_write_local(3, ym2612.REGS[i|0x100], 0); + } + for (i = 0xAF; i >= 0xA0; i--) { // must apply backwards + ym2612_write_local(2, i, 0); + ym2612_write_local(3, ym2612.REGS[i|0x100], 0); + ym2612_write_local(0, i, 0); + ym2612_write_local(1, ym2612.REGS[i], 0); + } + for (i = 0xB0; i < 0xB8; i++) { + ym2612_write_local(0, i, 0); + ym2612_write_local(1, ym2612.REGS[i], 0); + ym2612_write_local(2, i, 0); + ym2612_write_local(3, ym2612.REGS[i|0x100], 0); + } + +#ifdef __GP2X__ + if (PicoOpt & POPT_EXT_FM) + ret = YM2612PicoStateLoad2_940(&tat, &tbt); + else +#endif + ret = YM2612PicoStateLoad2(&tat, &tbt); + if (ret != 0) { + elprintf(EL_STATUS, "old ym2612 state"); + return; // no saved timers + } + + tac = (1024 - ym2612.OPN.ST.TA) << 16; + tbc = (256 - ym2612.OPN.ST.TB) << 16; + if (ym2612.OPN.ST.mode & 1) + timer_a_next_oflow = (int)((double)(tac - tat) / (double)tac * timer_a_step); + else + timer_a_next_oflow = TIMER_NO_OFLOW; + if (ym2612.OPN.ST.mode & 2) + timer_b_next_oflow = (int)((double)(tbc - tbt) / (double)tbc * timer_b_step); + else + timer_b_next_oflow = TIMER_NO_OFLOW; + elprintf(EL_YMTIMER, "load: %i/%i, timer_a_next_oflow %i", tat>>16, tac>>16, timer_a_next_oflow >> 8); + elprintf(EL_YMTIMER, "load: %i/%i, timer_b_next_oflow %i", tbt>>16, tbc>>16, timer_b_next_oflow >> 8); +} + +#if defined(NO_32X) && defined(_ASM_MEMORY_C) +// referenced by asm code +u32 PicoRead8_32x(u32 a) { return 0; } +u32 PicoRead16_32x(u32 a) { return 0; } +void PicoWrite8_32x(u32 a, u32 d) {} +void PicoWrite16_32x(u32 a, u32 d) {} +#endif + +// ----------------------------------------------------------------- +// z80 memhandlers + +static unsigned char z80_md_vdp_read(unsigned short a) +{ + // TODO? + elprintf(EL_ANOMALY, "z80 invalid r8 [%06x] %02x", a, 0xff); + return 0xff; +} + +static unsigned char z80_md_bank_read(unsigned short a) +{ + unsigned int addr68k; + unsigned char ret; + + addr68k = Pico.m.z80_bank68k<<15; + addr68k += a & 0x7fff; + + ret = m68k_read8(addr68k); + + elprintf(EL_Z80BNK, "z80->68k r8 [%06x] %02x", addr68k, ret); + return ret; +} + +static void z80_md_ym2612_write(unsigned int a, unsigned char data) +{ + if (PicoOpt & POPT_EN_FM) + emustatus |= ym2612_write_local(a, data, 1) & 1; +} + +static void z80_md_vdp_br_write(unsigned int a, unsigned char data) +{ + // TODO: allow full VDP access + if ((a&0xfff9) == 0x7f11) // 7f11 7f13 7f15 7f17 + { + if (PicoOpt & POPT_EN_PSG) + SN76496Write(data); + return; + } + + if ((a>>8) == 0x60) + { + Pico.m.z80_bank68k >>= 1; + Pico.m.z80_bank68k |= data << 8; + Pico.m.z80_bank68k &= 0x1ff; // 9 bits and filled in the new top one + return; + } + + elprintf(EL_ANOMALY, "z80 invalid w8 [%06x] %02x", a, data); +} + +static void z80_md_bank_write(unsigned int a, unsigned char data) +{ + unsigned int addr68k; + + addr68k = Pico.m.z80_bank68k << 15; + addr68k += a & 0x7fff; + + elprintf(EL_Z80BNK, "z80->68k w8 [%06x] %02x", addr68k, data); + m68k_write8(addr68k, data); +} + +// ----------------------------------------------------------------- + +static unsigned char z80_md_in(unsigned short p) +{ + elprintf(EL_ANOMALY, "Z80 port %04x read", p); + return 0xff; +} + +static void z80_md_out(unsigned short p, unsigned char d) +{ + elprintf(EL_ANOMALY, "Z80 port %04x write %02x", p, d); +} + +static void z80_mem_setup(void) +{ + z80_map_set(z80_read_map, 0x0000, 0x1fff, Pico.zram, 0); + z80_map_set(z80_read_map, 0x2000, 0x3fff, Pico.zram, 0); + z80_map_set(z80_read_map, 0x4000, 0x5fff, ym2612_read_local_z80, 1); + z80_map_set(z80_read_map, 0x6000, 0x7fff, z80_md_vdp_read, 1); + z80_map_set(z80_read_map, 0x8000, 0xffff, z80_md_bank_read, 1); + + z80_map_set(z80_write_map, 0x0000, 0x1fff, Pico.zram, 0); + z80_map_set(z80_write_map, 0x2000, 0x3fff, Pico.zram, 0); + z80_map_set(z80_write_map, 0x4000, 0x5fff, z80_md_ym2612_write, 1); + z80_map_set(z80_write_map, 0x6000, 0x7fff, z80_md_vdp_br_write, 1); + z80_map_set(z80_write_map, 0x8000, 0xffff, z80_md_bank_write, 1); + +#ifdef _USE_DRZ80 + drZ80.z80_in = z80_md_in; + drZ80.z80_out = z80_md_out; +#endif +#ifdef _USE_CZ80 + Cz80_Set_Fetch(&CZ80, 0x0000, 0x1fff, (FPTR)Pico.zram); // main RAM + Cz80_Set_Fetch(&CZ80, 0x2000, 0x3fff, (FPTR)Pico.zram); // mirror + Cz80_Set_INPort(&CZ80, z80_md_in); + Cz80_Set_OUTPort(&CZ80, z80_md_out); +#endif +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/memory.h b/waterbox/picodrive/pico/memory.h new file mode 100644 index 0000000000..afca082690 --- /dev/null +++ b/waterbox/picodrive/pico/memory.h @@ -0,0 +1,140 @@ +// memory map related stuff + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long uptr; // unsigned pointer-sized int + +#define M68K_MEM_SHIFT 16 +// minimum size we can map +#define M68K_BANK_SIZE (1 << M68K_MEM_SHIFT) +#define M68K_BANK_MASK (M68K_BANK_SIZE - 1) + +extern uptr m68k_read8_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr m68k_read16_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr m68k_write8_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr m68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; + +extern uptr s68k_read8_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr s68k_read16_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr s68k_write8_map [0x1000000 >> M68K_MEM_SHIFT]; +extern uptr s68k_write16_map[0x1000000 >> M68K_MEM_SHIFT]; + +// top-level handlers that cores can use +// (or alternatively build them into themselves) +// XXX: unhandled: *16 and *32 might cross the bank boundaries +typedef u32 (cpu68k_read_f)(u32 a); +typedef void (cpu68k_write_f)(u32 a, u32 d); + +extern u32 m68k_read8(u32 a); +extern u32 m68k_read16(u32 a); +extern void m68k_write8(u32 a, u8 d); +extern void m68k_write16(u32 a, u16 d); + +// z80 +#define Z80_MEM_SHIFT 13 +extern uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT]; +extern uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT]; +typedef unsigned char (z80_read_f)(unsigned short a); +typedef void (z80_write_f)(unsigned int a, unsigned char data); + +void z80_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func); +void cpu68k_map_set(uptr *map, int start_addr, int end_addr, + const void *func_or_mh, int is_func); +void cpu68k_map_all_ram(int start_addr, int end_addr, void *ptr, int is_sub); +void m68k_map_unmap(int start_addr, int end_addr); + +#define MAP_FLAG ((uptr)1 << (sizeof(uptr) * 8 - 1)) +#define map_flag_set(x) ((x) & MAP_FLAG) + +#define MAKE_68K_READ8(name, map) \ +u32 name(u32 a) \ +{ \ + uptr v; \ + a &= 0x00ffffff; \ + v = map[a >> M68K_MEM_SHIFT]; \ + if (map_flag_set(v)) \ + return ((cpu68k_read_f *)(v << 1))(a); \ + else \ + return *(u8 *)((v << 1) + (a ^ 1)); \ +} + +#define MAKE_68K_READ16(name, map) \ +u32 name(u32 a) \ +{ \ + uptr v; \ + a &= 0x00fffffe; \ + v = map[a >> M68K_MEM_SHIFT]; \ + if (map_flag_set(v)) \ + return ((cpu68k_read_f *)(v << 1))(a); \ + else \ + return *(u16 *)((v << 1) + a); \ +} + +#define MAKE_68K_READ32(name, map) \ +u32 name(u32 a) \ +{ \ + uptr v, vs; \ + u32 d; \ + a &= 0x00fffffe; \ + v = map[a >> M68K_MEM_SHIFT]; \ + vs = v << 1; \ + if (map_flag_set(v)) { \ + d = ((cpu68k_read_f *)vs)(a) << 16; \ + d |= ((cpu68k_read_f *)vs)(a + 2); \ + } \ + else { \ + u16 *m = (u16 *)(vs + a); \ + d = (m[0] << 16) | m[1]; \ + } \ + return d; \ +} + +#define MAKE_68K_WRITE8(name, map) \ +void name(u32 a, u8 d) \ +{ \ + uptr v; \ + a &= 0x00ffffff; \ + v = map[a >> M68K_MEM_SHIFT]; \ + if (map_flag_set(v)) \ + ((cpu68k_write_f *)(v << 1))(a, d); \ + else \ + *(u8 *)((v << 1) + (a ^ 1)) = d; \ +} + +#define MAKE_68K_WRITE16(name, map) \ +void name(u32 a, u16 d) \ +{ \ + uptr v; \ + a &= 0x00fffffe; \ + v = map[a >> M68K_MEM_SHIFT]; \ + if (map_flag_set(v)) \ + ((cpu68k_write_f *)(v << 1))(a, d); \ + else \ + *(u16 *)((v << 1) + a) = d; \ +} + +#define MAKE_68K_WRITE32(name, map) \ +void name(u32 a, u32 d) \ +{ \ + uptr v, vs; \ + a &= 0x00fffffe; \ + v = map[a >> M68K_MEM_SHIFT]; \ + vs = v << 1; \ + if (map_flag_set(v)) { \ + ((cpu68k_write_f *)vs)(a, d >> 16); \ + ((cpu68k_write_f *)vs)(a + 2, d); \ + } \ + else { \ + u16 *m = (u16 *)(vs + a); \ + m[0] = d >> 16; \ + m[1] = d; \ + } \ +} + +// 32x +typedef struct { + uptr addr; // stores (membase >> 1) or ((handler >> 1) | (1<<31)) + u32 mask; +} sh2_memmap; diff --git a/waterbox/picodrive/pico/misc.c b/waterbox/picodrive/pico/misc.c new file mode 100644 index 0000000000..a500ac8cc7 --- /dev/null +++ b/waterbox/picodrive/pico/misc.c @@ -0,0 +1,158 @@ +/* + * rarely used EEPROM code + * (C) notaz, 2006-2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" + +// H-counter table for hvcounter reads in 40col mode +// based on Gens code +const unsigned char hcounts_40[] = { +0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, +0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10,0x11,0x11,0x12,0x12,0x13,0x13,0x13,0x14, +0x14,0x15,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x1a,0x1a,0x1b, +0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21, +0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28, +0x28,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2f, +0x2f,0x30,0x30,0x30,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x34,0x34,0x35,0x35,0x35, +0x36,0x36,0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3c,0x3c, +0x3d,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42,0x42,0x43, +0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x49,0x49,0x4a, +0x4a,0x4a,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50, +0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x57,0x57, +0x57,0x58,0x58,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5e, +0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x64,0x64,0x64, +0x65,0x65,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b, +0x6c,0x6c,0x6c,0x6d,0x6d,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x71,0x71,0x71,0x72, +0x72,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x79, +0x79,0x79,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7e,0x7e,0x7f,0x7f,0x7f, +0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x84,0x84,0x84,0x85,0x85,0x86,0x86, +0x86,0x87,0x87,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d, +0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,0x92,0x93,0x93,0x94, +0x94,0x94,0x95,0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,0x99,0x99,0x99,0x9a,0x9a, +0x9b,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9e,0x9f,0x9f,0xa0,0xa0,0xa1,0xa1, +0xa1,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,0xa8, +0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,0xab,0xab,0xab,0xac,0xac,0xad,0xad,0xae,0xae,0xae, +0xaf,0xaf,0xb0,0xb0, +0xe4,0xe4,0xe4,0xe5,0xe5,0xe6,0xe6,0xe6,0xe7,0xe7,0xe8,0xe8,0xe9,0xe9,0xe9,0xea, +0xea,0xeb,0xeb,0xeb,0xec,0xec,0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf1, +0xf1,0xf1,0xf2,0xf2,0xf3,0xf3,0xf3,0xf4,0xf4,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7, +0xf8,0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfe,0xfe, +0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x05, +0x05,0x06,0x06,0x06, +0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0d,0x0d, +0x0e,0x0e,0x0e,0x0f,0x0f,0x10,0x10,0x10, +}; + +// H-counter table for hvcounter reads in 32col mode +const unsigned char hcounts_32[] = { +0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a, +0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0f,0x0f,0x0f,0x10, +0x10,0x10,0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15, +0x15,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b, +0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20, +0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x26,0x26, +0x26,0x27,0x27,0x27,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b, +0x2c,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,0x31,0x31, +0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x36,0x36,0x36,0x37, +0x37,0x37,0x38,0x38,0x38,0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c, +0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,0x41,0x41,0x41,0x42, +0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47, +0x48,0x48,0x48,0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4d,0x4d, +0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,0x51,0x51,0x51,0x52,0x52,0x52, +0x53,0x53,0x53,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58, +0x58,0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e, +0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63, +0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,0x69, +0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e, +0x6f,0x6f,0x6f,0x70,0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x74,0x74, +0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,0x79,0x79, +0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f, +0x7f,0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,0x83,0x83,0x83,0x84,0x84,0x84,0x85, +0x85,0x85,0x86,0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,0x89,0x89,0x89,0x8a,0x8a, +0x8b,0x8b,0x8b,0x8c,0x8c,0x8c,0x8d,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,0x8f,0x8f,0x90, +0x90,0x90,0x91,0x91, +0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xea,0xea,0xea,0xeb,0xeb,0xeb,0xec,0xec,0xec,0xed, +0xed,0xed,0xee,0xee,0xee,0xef,0xef,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf2,0xf2,0xf2, +0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf6,0xf6,0xf6,0xf7,0xf7,0xf8,0xf8, +0xf8,0xf9,0xf9,0xf9,0xfa,0xfa,0xfa,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfd,0xfd,0xfd, +0xfe,0xfe,0xfe,0xff,0xff,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03, +0x03,0x04,0x04,0x04, +0x05,0x05,0x05,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0a,0x0a, +0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d, +}; + + +#ifndef _ASM_MISC_C +typedef struct +{ + int b0; + int b1; + int b2; + int b3; + int b4; + int b5; + int b6; + int b7; +} intblock; + +PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count) +{ + if ((((long)dest | (long)src) & 3) == 0) + { + if (count >= 32) { + memcpy32((int *)dest, (int *)src, count/2); + count&=1; + } else { + for (; count >= 2; count -= 2, dest+=2, src+=2) + *(int *)dest = *(int *)src; + } + } + while (count--) + *dest++ = *src++; +} + + +PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count) +{ + unsigned char *src_ = src; + + for (; count; count--, src_ += 2) + *dest++ = (src_[0] << 8) | src_[1]; +} + +#ifndef _ASM_MISC_C_AMIPS +PICO_INTERNAL_ASM void memcpy32(void *dest_in, const void *src_in, int count) +{ + const intblock *bs = (intblock *) src_in; + intblock *bd = (intblock *) dest_in; + const int *src; + int *dest; + + for (; count >= sizeof(*bd)/4; count -= sizeof(*bd)/4) + *bd++ = *bs++; + + dest = (int *)bd; src = (const int *)bs; + while (count--) + *dest++ = *src++; +} + + +PICO_INTERNAL_ASM void memset32(void *dest_in, int c, int count) +{ + int *dest = dest_in; + + for (; count >= 8; count -= 8, dest += 8) + dest[0] = dest[1] = dest[2] = dest[3] = + dest[4] = dest[5] = dest[6] = dest[7] = c; + + while (count--) + *dest++ = c; +} +void memset32_uncached(int *dest, int c, int count) { memset32(dest, c, count); } +#endif +#endif + diff --git a/waterbox/picodrive/pico/mode4.c b/waterbox/picodrive/pico/mode4.c new file mode 100644 index 0000000000..22e30419b5 --- /dev/null +++ b/waterbox/picodrive/pico/mode4.c @@ -0,0 +1,302 @@ +/* + * mode4/SMS renderer + * (C) notaz, 2009-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +/* + * TODO: + * - TMS9918 modes? + * - gg mode? + * - column scroll (reg 0 bit7) + * - 224/240 line modes + * - doubled sprites + */ +#include "pico_int.h" + +static void (*FinalizeLineM4)(int line); +static int skip_next_line; +static int screen_offset; + +#define PLANAR_PIXEL(x,p) \ + t = pack & (0x80808080 >> p); \ + if (t) { \ + t = ((t >> (7-p)) | (t >> (14-p)) | (t >> (21-p)) | (t >> (28-p))) & 0x0f; \ + pd[x] = pal|t; \ + } + +static int TileNormM4(int sx, int addr, int pal) +{ + unsigned char *pd = HighCol + sx; + unsigned int pack, t; + + pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + if (pack) + { + PLANAR_PIXEL(0, 0) + PLANAR_PIXEL(1, 1) + PLANAR_PIXEL(2, 2) + PLANAR_PIXEL(3, 3) + PLANAR_PIXEL(4, 4) + PLANAR_PIXEL(5, 5) + PLANAR_PIXEL(6, 6) + PLANAR_PIXEL(7, 7) + return 0; + } + + return 1; /* Tile blank */ +} + +static int TileFlipM4(int sx,int addr,int pal) +{ + unsigned char *pd = HighCol + sx; + unsigned int pack, t; + + pack = *(unsigned int *)(Pico.vram + addr); /* Get 4 bitplanes / 8 pixels */ + if (pack) + { + PLANAR_PIXEL(0, 7) + PLANAR_PIXEL(1, 6) + PLANAR_PIXEL(2, 5) + PLANAR_PIXEL(3, 4) + PLANAR_PIXEL(4, 3) + PLANAR_PIXEL(5, 2) + PLANAR_PIXEL(6, 1) + PLANAR_PIXEL(7, 0) + return 0; + } + + return 1; /* Tile blank */ +} + +static void draw_sprites(int scanline) +{ + struct PicoVideo *pv = &Pico.video; + unsigned int sprites_addr[8]; + unsigned int sprites_x[8]; + unsigned char *sat; + int xoff = 8; // relative to HighCol, which is (screen - 8) + int sprite_base, addr_mask; + int i, s, h; + + if (pv->reg[0] & 8) + xoff = 0; + + sat = (unsigned char *)Pico.vram + ((pv->reg[5] & 0x7e) << 7); + if (pv->reg[1] & 2) { + addr_mask = 0xfe; h = 16; + } else { + addr_mask = 0xff; h = 8; + } + sprite_base = (pv->reg[6] & 4) << (13-2-1); + + for (i = s = 0; i < 64 && s < 8; i++) + { + int y; + y = sat[i] + 1; + if (y == 0xd1) + break; + if (y + h <= scanline || scanline < y) + continue; // not on this line + + sprites_x[s] = xoff + sat[0x80 + i*2]; + sprites_addr[s] = sprite_base + ((sat[0x80 + i*2 + 1] & addr_mask) << (5-1)) + + ((scanline - y) << (2-1)); + s++; + } + + // now draw all sprites backwards + for (--s; s >= 0; s--) + TileNormM4(sprites_x[s], sprites_addr[s], 0x10); +} + +// tilex_ty_prio merged to reduce register pressure +static void draw_strip(const unsigned short *nametab, int dx, int cells, int tilex_ty_prio) +{ + int oldcode = -1, blank = -1; // The tile we know is blank + int addr = 0, pal = 0; + + // Draw tiles across screen: + for (; cells > 0; dx += 8, tilex_ty_prio++, cells--) + { + int code, zero; + + code = nametab[tilex_ty_prio & 0x1f]; + if (code == blank) + continue; + if ((code ^ tilex_ty_prio) & 0x1000) // priority differs? + continue; + + if (code != oldcode) { + oldcode = code; + // Get tile address/2: + addr = (code & 0x1ff) << 4; + addr += tilex_ty_prio >> 16; + if (code & 0x0400) + addr ^= 0xe; // Y-flip + + pal = (code>>7) & 0x10; + } + + if (code&0x0200) zero = TileFlipM4(dx, addr, pal); + else zero = TileNormM4(dx, addr, pal); + + if (zero) + blank = code; // We know this tile is blank now + } +} + +static void DrawDisplayM4(int scanline) +{ + struct PicoVideo *pv = &Pico.video; + unsigned short *nametab; + int line, tilex, dx, ty, cells; + int cellskip = 0; // XXX + int maxcells = 32; + + // Find the line in the name table + line = pv->reg[9] + scanline; // vscroll + scanline + if (line >= 224) + line -= 224; + + // Find name table: + nametab = Pico.vram; + nametab += (pv->reg[2] & 0x0e) << (10-1); + nametab += (line>>3) << (6-1); + + dx = pv->reg[8]; // hscroll + if (scanline < 16 && (pv->reg[0] & 0x40)) + dx = 0; // hscroll disabled for top 2 rows + + tilex = ((-dx >> 3) + cellskip) & 0x1f; + ty = (line & 7) << 1; // Y-Offset into tile + cells = maxcells - cellskip; + + dx = ((dx - 1) & 7) + 1; + if (dx != 8) + cells++; // have hscroll, need to draw 1 cell more + dx += cellskip << 3; + + // low priority tiles + if (PicoDrawMask & PDRAW_LAYERB_ON) + draw_strip(nametab, dx, cells, tilex | 0x0000 | (ty << 16)); + + // sprites + if (PicoDrawMask & PDRAW_SPRITES_LOW_ON) + draw_sprites(scanline); + + // high priority tiles (use virtual layer switch just for fun) + if (PicoDrawMask & PDRAW_LAYERA_ON) + draw_strip(nametab, dx, cells, tilex | 0x1000 | (ty << 16)); + + if (pv->reg[0] & 0x20) + // first column masked + ((int *)HighCol)[2] = ((int *)HighCol)[3] = 0xe0e0e0e0; +} + +void PicoFrameStartMode4(void) +{ + int lines = 192; + skip_next_line = 0; + screen_offset = 24; + rendstatus = PDRAW_32_COLS; + + if ((Pico.video.reg[0] & 6) == 6 && (Pico.video.reg[1] & 0x18)) { + if (Pico.video.reg[1] & 0x08) { + screen_offset = 0; + lines = 240; + } + else { + screen_offset = 8; + lines = 224; + } + } + + if (rendstatus != rendstatus_old || lines != rendlines) { + emu_video_mode_change(screen_offset, lines, 1); + rendstatus_old = rendstatus; + rendlines = lines; + } + + DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement; +} + +void PicoLineMode4(int line) +{ + if (skip_next_line > 0) { + skip_next_line--; + return; + } + + if (PicoScanBegin != NULL) + skip_next_line = PicoScanBegin(line + screen_offset); + + // Draw screen: + BackFill(Pico.video.reg[7] & 0x0f, 0); + if (Pico.video.reg[1] & 0x40) + DrawDisplayM4(line); + + if (FinalizeLineM4 != NULL) + FinalizeLineM4(line); + + if (PicoScanEnd != NULL) + skip_next_line = PicoScanEnd(line + screen_offset); + + DrawLineDest = (char *)DrawLineDest + DrawLineDestIncrement; +} + +void PicoDoHighPal555M4(void) +{ + unsigned int *spal=(void *)Pico.cram; + unsigned int *dpal=(void *)HighPal; + unsigned int t; + int i; + + Pico.m.dirtyPal = 0; + + /* cram is always stored as shorts, even though real hardware probably uses bytes */ + for (i = 0x20/2; i > 0; i--, spal++, dpal++) { + t = *spal; +#ifdef USE_BGR555 + t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10); +#else + t = ((t & 0x00030003)<<14) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)>>1); +#endif + t |= t >> 2; + t |= (t >> 4) & 0x08610861; + *dpal = t; + } + HighPal[0xe0] = 0; +} + +static void FinalizeLineRGB555M4(int line) +{ + if (Pico.m.dirtyPal) + PicoDoHighPal555M4(); + + // standard FinalizeLine can finish it for us, + // with features like scaling and such + FinalizeLine555(0, line); +} + +static void FinalizeLine8bitM4(int line) +{ + unsigned char *pd = DrawLineDest; + + if (!(PicoOpt & POPT_DIS_32C_BORDER)) + pd += 32; + + memcpy32((int *)pd, (int *)(HighCol+8), 256/4); +} + +void PicoDrawSetOutputMode4(pdso_t which) +{ + switch (which) + { + case PDF_8BIT: FinalizeLineM4 = FinalizeLine8bitM4; break; + case PDF_RGB555: FinalizeLineM4 = FinalizeLineRGB555M4; break; + default: FinalizeLineM4 = NULL; break; + } +} + diff --git a/waterbox/picodrive/pico/pico.c b/waterbox/picodrive/pico/pico.c new file mode 100644 index 0000000000..188926e5f6 --- /dev/null +++ b/waterbox/picodrive/pico/pico.c @@ -0,0 +1,345 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" +#include "sound/ym2612.h" + +struct Pico Pico; +int PicoOpt; +int PicoSkipFrame; // skip rendering frame? +int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU +int PicoPadInt[2]; // internal copy +int PicoAHW; // active addon hardware: PAHW_* +int PicoQuirks; // game-specific quirks +int PicoRegionOverride; // override the region detection 0: Auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe +int PicoAutoRgnOrder; + +struct PicoSRAM SRam; +int emustatus; // rapid_ym2612, multi_ym_updates +int scanlines_total; + +void (*PicoWriteSound)(int len) = NULL; // called at the best time to send sound buffer (PsndOut) to hardware +void (*PicoResetHook)(void) = NULL; +void (*PicoLineHook)(void) = NULL; + +// to be called once on emu init +void PicoInit(void) +{ + // Blank space for state: + memset(&Pico,0,sizeof(Pico)); + memset(&PicoPad,0,sizeof(PicoPad)); + memset(&PicoPadInt,0,sizeof(PicoPadInt)); + + // Init CPUs: + SekInit(); + z80_init(); // init even if we aren't going to use it + + PicoInitMCD(); + PicoSVPInit(); + Pico32xInit(); +} + +void PicoPower(void) +{ + Pico.m.frame_count = 0; + SekCycleCnt = SekCycleAim = 0; + + // clear all memory of the emulated machine + memset(&Pico.ram,0,(unsigned char *)&Pico.rom - Pico.ram); + + memset(&Pico.video,0,sizeof(Pico.video)); + memset(&Pico.m,0,sizeof(Pico.m)); + + Pico.video.pending_ints=0; + z80_reset(); + + // my MD1 VA6 console has this in IO + Pico.ioports[1] = Pico.ioports[2] = Pico.ioports[3] = 0xff; + + // default VDP register values (based on Fusion) + Pico.video.reg[0] = Pico.video.reg[1] = 0x04; + Pico.video.reg[0xc] = 0x81; + Pico.video.reg[0xf] = 0x02; + + if (PicoAHW & PAHW_MCD) + PicoPowerMCD(); + + if (PicoOpt & POPT_EN_32X) + PicoPower32x(); + + PicoReset(); +} + +PICO_INTERNAL void PicoDetectRegion(void) +{ + int support=0, hw=0, i; + unsigned char pal=0; + + if (PicoRegionOverride) + { + support = PicoRegionOverride; + } + else + { + // Read cartridge region data: + unsigned short *rd = (unsigned short *)(Pico.rom + 0x1f0); + int region = (rd[0] << 16) | rd[1]; + + for (i = 0; i < 4; i++) + { + int c; + + c = region >> (i<<3); + c &= 0xff; + if (c <= ' ') continue; + + if (c=='J') support|=1; + else if (c=='U') support|=4; + else if (c=='E') support|=8; + else if (c=='j') {support|=1; break; } + else if (c=='u') {support|=4; break; } + else if (c=='e') {support|=8; break; } + else + { + // New style code: + char s[2]={0,0}; + s[0]=(char)c; + support|=strtol(s,NULL,16); + } + } + } + + // auto detection order override + if (PicoAutoRgnOrder) { + if (((PicoAutoRgnOrder>>0)&0xf) & support) support = (PicoAutoRgnOrder>>0)&0xf; + else if (((PicoAutoRgnOrder>>4)&0xf) & support) support = (PicoAutoRgnOrder>>4)&0xf; + else if (((PicoAutoRgnOrder>>8)&0xf) & support) support = (PicoAutoRgnOrder>>8)&0xf; + } + + // Try to pick the best hardware value for English/50hz: + if (support&8) { hw=0xc0; pal=1; } // Europe + else if (support&4) hw=0x80; // USA + else if (support&2) { hw=0x40; pal=1; } // Japan PAL + else if (support&1) hw=0x00; // Japan NTSC + else hw=0x80; // USA + + Pico.m.hardware=(unsigned char)(hw|0x20); // No disk attached + Pico.m.pal=pal; +} + +int PicoReset(void) +{ + if (Pico.romsize <= 0) + return 1; + +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) || defined(DRC_CMP) + PicoOpt |= POPT_DIS_VDP_FIFO|POPT_DIS_IDLE_DET; +#endif + + /* must call now, so that banking is reset, and correct vectors get fetched */ + if (PicoResetHook) + PicoResetHook(); + + memset(&PicoPadInt,0,sizeof(PicoPadInt)); + emustatus = 0; + + if (PicoAHW & PAHW_SMS) { + PicoResetMS(); + return 0; + } + + SekReset(); + // ..but do not reset SekCycle* to not desync with addons + + // s68k doesn't have the TAS quirk, so we just globally set normal TAS handler in MCD mode (used by Batman games). + SekSetRealTAS(PicoAHW & PAHW_MCD); + + Pico.m.dirtyPal = 1; + + Pico.m.z80_bank68k = 0; + Pico.m.z80_reset = 1; + + PicoDetectRegion(); + Pico.video.status = 0x3428 | Pico.m.pal; // 'always set' bits | vblank | collision | pal + + PsndReset(); // pal must be known here + + // create an empty "dma" to cause 68k exec start at random frame location + if (Pico.m.dma_xfers == 0 && !(PicoOpt & POPT_DIS_VDP_FIFO)) + Pico.m.dma_xfers = rand() & 0x1fff; + + SekFinishIdleDet(); + + if (PicoAHW & PAHW_MCD) { + PicoResetMCD(); + return 0; + } + + // reinit, so that checksum checks pass + if (!(PicoOpt & POPT_DIS_IDLE_DET)) + SekInitIdleDet(); + + if (PicoOpt & POPT_EN_32X) + PicoReset32x(); + + // reset sram state; enable sram access by default if it doesn't overlap with ROM + Pico.m.sram_reg = 0; + if ((SRam.flags & SRF_EEPROM) || Pico.romsize <= SRam.start) + Pico.m.sram_reg |= SRR_MAPPED; + + if (SRam.flags & SRF_ENABLED) + elprintf(EL_STATUS, "sram: %06x - %06x; eeprom: %i", SRam.start, SRam.end, + !!(SRam.flags & SRF_EEPROM)); + + return 0; +} + +// flush config changes before emu loop starts +void PicoLoopPrepare(void) +{ + if (PicoRegionOverride) + // force setting possibly changed.. + Pico.m.pal = (PicoRegionOverride == 2 || PicoRegionOverride == 8) ? 1 : 0; + + // FIXME: PAL has 313 scanlines.. + scanlines_total = Pico.m.pal ? 312 : 262; + + Pico.m.dirtyPal = 1; + rendstatus_old = -1; +} + + +// dma2vram settings are just hacks to unglitch Legend of Galahad (needs <= 104 to work) +// same for Outrunners (92-121, when active is set to 24) +// 96 is VR hack +static const int dma_timings[] = { + 167, 167, 166, 83, // vblank: 32cell: dma2vram dma2[vs|c]ram vram_fill vram_copy + 102, 205, 204, 102, // vblank: 40cell: + 16, 16, 15, 8, // active: 32cell: + 24, 18, 17, 9 // ... +}; + +static const int dma_bsycles[] = { + (488<<8)/167, (488<<8)/167, (488<<8)/166, (488<<8)/83, + (488<<8)/102, (488<<8)/233, (488<<8)/204, (488<<8)/102, + (488<<8)/16, (488<<8)/16, (488<<8)/15, (488<<8)/8, + (488<<8)/24, (488<<8)/18, (488<<8)/17, (488<<8)/9 +}; + +// grossly inaccurate.. FIXME FIXXXMEE +PICO_INTERNAL int CheckDMA(void) +{ + int burn = 0, xfers_can, dma_op = Pico.video.reg[0x17]>>6; // see gens for 00 and 01 modes + int xfers = Pico.m.dma_xfers; + int dma_op1; + + if(!(dma_op&2)) dma_op = (Pico.video.type==1) ? 0 : 1; // setting dma_timings offset here according to Gens + dma_op1 = dma_op; + if(Pico.video.reg[12] & 1) dma_op |= 4; // 40 cell mode? + if(!(Pico.video.status&8)&&(Pico.video.reg[1]&0x40)) dma_op|=8; // active display? + xfers_can = dma_timings[dma_op]; + if(xfers <= xfers_can) + { + if(dma_op&2) Pico.video.status&=~2; // dma no longer busy + else { + burn = xfers * dma_bsycles[dma_op] >> 8; // have to be approximate because can't afford division.. + } + Pico.m.dma_xfers = 0; + } else { + if(!(dma_op&2)) burn = 488; + Pico.m.dma_xfers -= xfers_can; + } + + elprintf(EL_VDPDMA, "~Dma %i op=%i can=%i burn=%i [%i]", Pico.m.dma_xfers, dma_op1, xfers_can, burn, SekCyclesDone()); + //dprintf("~aim: %i, cnt: %i", SekCycleAim, SekCycleCnt); + return burn; +} + +#include "pico_cmn.inc" + +unsigned int last_z80_sync; /* in 68k cycles */ +int z80_cycle_cnt; +int z80_cycle_aim; +int z80_scanline; +int z80_scanline_cycles; /* cycles done until z80_scanline */ + +/* sync z80 to 68k */ +PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done) +{ + int m68k_cnt; + int cnt; + + m68k_cnt = m68k_cycles_done - last_z80_sync; + z80_cycle_aim += cycles_68k_to_z80(m68k_cnt); + cnt = z80_cycle_aim - z80_cycle_cnt; + last_z80_sync = m68k_cycles_done; + + pprof_start(z80); + + elprintf(EL_BUSREQ, "z80 sync %i (%u|%u -> %u|%u)", cnt, + z80_cycle_cnt, z80_cycle_cnt / 288, + z80_cycle_aim, z80_cycle_aim / 288); + + if (cnt > 0) + z80_cycle_cnt += z80_run(cnt); + + pprof_end(z80); +} + + +void PicoFrame(void) +{ + pprof_start(frame); + + Pico.m.frame_count++; + + if (PicoAHW & PAHW_SMS) { + PicoFrameMS(); + goto end; + } + + if (PicoAHW & PAHW_32X) { + PicoFrame32x(); // also does MCD+32X + goto end; + } + + if (PicoAHW & PAHW_MCD) { + PicoFrameMCD(); + goto end; + } + + //if(Pico.video.reg[12]&0x2) Pico.video.status ^= 0x10; // change odd bit in interlace mode + + PicoFrameStart(); + PicoFrameHints(); + +end: + pprof_end(frame); +} + +void PicoFrameDrawOnly(void) +{ + if (!(PicoAHW & PAHW_SMS)) { + PicoFrameStart(); + PicoDrawSync(223, 0); + } else { + PicoFrameDrawOnlyMS(); + } +} + +void PicoGetInternal(pint_t which, pint_ret_t *r) +{ + switch (which) + { + case PI_ROM: r->vptr = Pico.rom; break; + case PI_ISPAL: r->vint = Pico.m.pal; break; + case PI_IS40_CELL: r->vint = Pico.video.reg[12]&1; break; + case PI_IS240_LINES: r->vint = Pico.m.pal && (Pico.video.reg[1]&8); break; + } +} diff --git a/waterbox/picodrive/pico/pico.h b/waterbox/picodrive/pico/pico.h new file mode 100644 index 0000000000..efa8e1d9cb --- /dev/null +++ b/waterbox/picodrive/pico/pico.h @@ -0,0 +1,246 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#ifndef PICO_H +#define PICO_H + +#include // size_t + +#ifdef __cplusplus +extern "C" { +#endif + +// message log +extern void lprintf(const char *fmt, ...); + +// external funcs for Sega/Mega CD +extern int mp3_get_bitrate(void *f, int size); +extern void mp3_start_play(void *f, int pos); +extern void mp3_update(int *buffer, int length, int stereo); + +// this one should handle display mode changes +extern void emu_video_mode_change(int start_line, int line_count, int is_32cols); + +// this must switch to 16bpp mode +extern void emu_32x_startup(void); + +// optional 32X BIOS, should be left NULL if not used +// must be 256, 2048, 1024 bytes +extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s; + +// Pico.c +#define POPT_EN_FM (1<< 0) // 00 000x +#define POPT_EN_PSG (1<< 1) +#define POPT_EN_Z80 (1<< 2) +#define POPT_EN_STEREO (1<< 3) +#define POPT_ALT_RENDERER (1<< 4) // 00 00x0 +// unused (1<< 5) +// unused (1<< 6) +#define POPT_ACC_SPRITES (1<< 7) +#define POPT_DIS_32C_BORDER (1<< 8) // 00 0x00 +#define POPT_EXT_FM (1<< 9) +#define POPT_EN_MCD_PCM (1<<10) +#define POPT_EN_MCD_CDDA (1<<11) +#define POPT_EN_MCD_GFX (1<<12) // 00 x000 +// unused (1<<13) +#define POPT_EN_SOFTSCALE (1<<14) +#define POPT_EN_MCD_RAMCART (1<<15) +#define POPT_DIS_VDP_FIFO (1<<16) // 0x 0000 +#define POPT_EN_DRC (1<<17) +#define POPT_DIS_SPRITE_LIM (1<<18) +#define POPT_DIS_IDLE_DET (1<<19) +#define POPT_EN_32X (1<<20) +#define POPT_EN_PWM (1<<21) +extern int PicoOpt; // bitfield + +#define PAHW_MCD (1<<0) +#define PAHW_32X (1<<1) +#define PAHW_SVP (1<<2) +#define PAHW_PICO (1<<3) +#define PAHW_SMS (1<<4) +extern int PicoAHW; // Pico active hw + +#define PQUIRK_FORCE_6BTN (1<<0) +extern int PicoQuirks; + +extern int PicoSkipFrame; // skip rendering frame, but still do sound (if enabled) and emulation stuff +extern int PicoRegionOverride; // override the region detection 0: auto, 1: Japan NTSC, 2: Japan PAL, 4: US, 8: Europe +extern int PicoAutoRgnOrder; // packed priority list of regions, for example 0x148 means this detection order: EUR, USA, JAP +extern int PicoSVPCycles; +void PicoInit(void); +void PicoPower(void); +int PicoReset(void); +void PicoLoopPrepare(void); +void PicoFrame(void); +void PicoFrameDrawOnly(void); +extern int PicoPad[2]; // Joypads, format is MXYZ SACB RLDU +extern void (*PicoWriteSound)(int bytes); // called once per frame at the best time to send sound buffer (PsndOut) to hardware +typedef enum { PI_ROM, PI_ISPAL, PI_IS40_CELL, PI_IS240_LINES } pint_t; +typedef union { int vint; void *vptr; } pint_ret_t; +void PicoGetInternal(pint_t which, pint_ret_t *ret); + +// cd/mcd.c +extern void (*PicoMCDopenTray)(void); +extern void (*PicoMCDcloseTray)(void); + +// pico.c +#define XPCM_BUFFER_SIZE (320+160) +typedef struct +{ + int pen_pos[2]; + int page; + // internal + int fifo_bytes; // bytes in FIFO + int fifo_bytes_prev; + int fifo_line_bytes; // float part, << 16 + int line_counter; + unsigned short r1, r12; + unsigned char xpcm_buffer[XPCM_BUFFER_SIZE+4]; + unsigned char *xpcm_ptr; +} picohw_state; +extern picohw_state PicoPicohw; + +// cd/cdd.c +int cdd_load(const char *filename, int type); + +// Cart.c +typedef enum +{ + PMT_UNCOMPRESSED = 0, + PMT_ZIP, + PMT_CSO +} pm_type; +typedef struct +{ + void *file; /* file handle */ + void *param; /* additional file related field */ + unsigned int size; /* size */ + pm_type type; + char ext[4]; +} pm_file; +pm_file *pm_open(const char *path); +size_t pm_read(void *ptr, size_t bytes, pm_file *stream); +int pm_seek(pm_file *stream, long offset, int whence); +int pm_close(pm_file *fp); +int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize,int is_sms); +int PicoCartInsert(unsigned char *rom, unsigned int romsize, const char *carthw_cfg); +extern void (*PicoCDLoadProgressCB)(const char *fname, int percent); +extern int PicoGameLoaded; + +// Draw.c +// for line-based renderer, set conversion +// from internal 8 bit representation in 'HighCol' to: +typedef enum +{ + PDF_NONE = 0, // no conversion + PDF_RGB555, // RGB/BGR output, depends on compile options + PDF_8BIT, // 8-bit out (handles shadow/hilight mode, sonic water) +} pdso_t; +void PicoDrawSetOutFormat(pdso_t which, int use_32x_line_mode); +void PicoDrawSetOutBuf(void *dest, int increment); +void PicoDrawSetCallbacks(int (*begin)(unsigned int num), int (*end)(unsigned int num)); +extern void *DrawLineDest; +extern unsigned char *HighCol; +// utility +#ifdef _ASM_DRAW_C +void vidConvCpyRGB565(void *to, void *from, int pixels); +#endif +void PicoDoHighPal555(int sh); +extern int PicoDrawMask; +#define PDRAW_LAYERB_ON (1<<2) +#define PDRAW_LAYERA_ON (1<<3) +#define PDRAW_SPRITES_LOW_ON (1<<4) +#define PDRAW_SPRITES_HI_ON (1<<7) +#define PDRAW_32X_ON (1<<8) +// internals +#define PDRAW_SPRITES_MOVED (1<<0) // (asm) +#define PDRAW_WND_DIFF_PRIO (1<<1) // not all window tiles use same priority +#define PDRAW_SPR_LO_ON_HI (1<<2) // seen sprites without layer pri bit ontop spr. with that bit +#define PDRAW_INTERLACE (1<<3) +#define PDRAW_DIRTY_SPRITES (1<<4) // (asm) +#define PDRAW_SONIC_MODE (1<<5) // mid-frame palette changes for 8bit renderer +#define PDRAW_PLANE_HI_PRIO (1<<6) // have layer with all hi prio tiles (mk3) +#define PDRAW_SHHI_DONE (1<<7) // layer sh/hi already processed +#define PDRAW_32_COLS (1<<8) // 32 column mode +extern int rendstatus, rendstatus_old; +extern int rendlines; +extern unsigned short HighPal[0x100]; + +// draw.c +void PicoDrawUpdateHighPal(void); +void PicoDrawSetInternalBuf(void *dest, int line_increment); + +// draw2.c +// stuff below is optional +extern unsigned char *PicoDraw2FB; // buffer for fast renderer in format (8+320)x(8+224+8) (eights for borders) +extern unsigned short *PicoCramHigh; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now) +extern void (*PicoPrepareCram)(); // prepares PicoCramHigh for renderer to use + +// pico.c (32x) +#ifndef NO_32X + +void Pico32xSetClocks(int msh2_hz, int ssh2_hz); + +#else + +#define Pico32xSetClocks(msh2_khz, ssh2_khz) + +#endif + +// normally 68k clock (7670442) * 3, in reality but much lower +// because of high memory latencies +#define PICO_MSH2_HZ ((int)(7670442.0 * 2.4)) +#define PICO_SSH2_HZ ((int)(7670442.0 * 2.4)) + +// sound.c +extern int PsndRate,PsndLen; +extern short *PsndOut; +extern void (*PsndMix_32_to_16l)(short *dest, int *src, int count); +void PsndRerate(int preserve_state); + +// media.c +enum media_type_e { + PM_BAD_DETECT = -1, + PM_ERROR = -2, + PM_BAD_CD = -3, + PM_BAD_CD_NO_BIOS = -4, + PM_MD_CART = 1, /* also 32x */ + PM_MARK3, + PM_CD, +}; + +enum cd_img_type +{ + CIT_NOT_CD = 0, + CIT_ISO, + CIT_BIN, + CIT_CUE +}; + +enum media_type_e PicoLoadMedia(const char *filename, + const char *carthw_cfg_fname, + const char *(*get_bios_filename)(int *region, const char *cd_fname), + void (*do_region_override)(const char *media_filename), enum media_type_e media_type); +int PicoCdCheck(const char *fname_in, int *pregion); + +extern unsigned char media_id_header[0x100]; + +// memory.c +enum input_device { + PICO_INPUT_NOTHING, + PICO_INPUT_PAD_3BTN, + PICO_INPUT_PAD_6BTN, +}; +void PicoSetInputDevice(int port, enum input_device device); + +#ifdef __cplusplus +} // End of extern "C" +#endif + +#endif // PICO_H diff --git a/waterbox/picodrive/pico/pico/memory.c b/waterbox/picodrive/pico/pico/memory.c new file mode 100644 index 0000000000..7c3a64636d --- /dev/null +++ b/waterbox/picodrive/pico/pico/memory.c @@ -0,0 +1,124 @@ +/* + * PicoDrive + * (C) notaz, 2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include "../pico_int.h" +#include "../memory.h" +#include "../sound/sn76496.h" + +/* +void dump(u16 w) +{ + static FILE *f[0x10] = { NULL, }; + char fname[32]; + int num = PicoPicohw.r12 & 0xf; + + w = (w << 8) | (w >> 8); + sprintf(fname, "ldump%i.bin", num); + if (f[num] == NULL) + f[num] = fopen(fname, "wb"); + fwrite(&w, 1, 2, f[num]); + //fclose(f); +} +*/ + +static u32 PicoRead8_pico(u32 a) +{ + u32 d = 0; + + if ((a & 0xffffe0) == 0x800000) // Pico I/O + { + switch (a & 0x1f) + { + case 0x01: d = PicoPicohw.r1; break; + case 0x03: + d = PicoPad[0]&0x1f; // d-pad + d |= (PicoPad[0]&0x20) << 2; // pen push -> C + d = ~d; + break; + + case 0x05: d = (PicoPicohw.pen_pos[0] >> 8); break; // what is MS bit for? Games read it.. + case 0x07: d = PicoPicohw.pen_pos[0] & 0xff; break; + case 0x09: d = (PicoPicohw.pen_pos[1] >> 8); break; + case 0x0b: d = PicoPicohw.pen_pos[1] & 0xff; break; + case 0x0d: d = (1 << (PicoPicohw.page & 7)) - 1; break; + case 0x12: d = PicoPicohw.fifo_bytes == 0 ? 0x80 : 0; break; // guess + default: + goto unhandled; + } + return d; + } + +unhandled: + elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc); + return d; +} + +static u32 PicoRead16_pico(u32 a) +{ + u32 d = 0; + + if (a == 0x800010) + d = (PicoPicohw.fifo_bytes > 0x3f) ? 0 : (0x3f - PicoPicohw.fifo_bytes); + else if (a == 0x800012) + d = PicoPicohw.fifo_bytes == 0 ? 0x8000 : 0; // guess + else + elprintf(EL_UIO, "m68k unmapped r16 [%06x] @%06x", a, SekPc); + + return d; +} + +static void PicoWrite8_pico(u32 a, u32 d) +{ + switch (a & ~0x800000) { + case 0x19: case 0x1b: case 0x1d: case 0x1f: break; // 'S' 'E' 'G' 'A' + default: + elprintf(EL_UIO, "m68k unmapped w8 [%06x] %02x @%06x", a, d & 0xff, SekPc); + break; + } +} + +static void PicoWrite16_pico(u32 a, u32 d) +{ + //if (a == 0x800010) dump(d); + if (a == 0x800010) + { + PicoPicohw.fifo_bytes += 2; + + if (PicoPicohw.xpcm_ptr < PicoPicohw.xpcm_buffer + XPCM_BUFFER_SIZE) { + *PicoPicohw.xpcm_ptr++ = d >> 8; + *PicoPicohw.xpcm_ptr++ = d; + } + else if (PicoPicohw.xpcm_ptr == PicoPicohw.xpcm_buffer + XPCM_BUFFER_SIZE) { + elprintf(EL_ANOMALY|EL_PICOHW, "xpcm_buffer overflow!"); + PicoPicohw.xpcm_ptr++; + } + } + else if (a == 0x800012) { + int r12_old = PicoPicohw.r12; + PicoPicohw.r12 = d; + if (r12_old != d) + PicoReratePico(); + } + else + elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc); +} + + +PICO_INTERNAL void PicoMemSetupPico(void) +{ + PicoMemSetup(); + + // no MD IO or Z80 on Pico + m68k_map_unmap(0x400000, 0xbfffff); + + // map Pico I/O + cpu68k_map_set(m68k_read8_map, 0x800000, 0x80ffff, PicoRead8_pico, 1); + cpu68k_map_set(m68k_read16_map, 0x800000, 0x80ffff, PicoRead16_pico, 1); + cpu68k_map_set(m68k_write8_map, 0x800000, 0x80ffff, PicoWrite8_pico, 1); + cpu68k_map_set(m68k_write16_map, 0x800000, 0x80ffff, PicoWrite16_pico, 1); +} + diff --git a/waterbox/picodrive/pico/pico/pico.c b/waterbox/picodrive/pico/pico/pico.c new file mode 100644 index 0000000000..bff5a2a4e3 --- /dev/null +++ b/waterbox/picodrive/pico/pico/pico.c @@ -0,0 +1,104 @@ +/* + * PicoDrive + * (C) notaz, 2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +#include "../pico_int.h" + +// x: 0x03c - 0x19d +// y: 0x1fc - 0x2f7 +// 0x2f8 - 0x3f3 +picohw_state PicoPicohw; + +static int prev_line_cnt_irq3 = 0, prev_line_cnt_irq5 = 0; +static int fifo_bytes_line = (16000<<16)/60/262/2; + +static const int guessed_rates[] = { 8000, 14000, 12000, 14000, 16000, 18000, 16000, 16000 }; // ? + +#define PICOHW_FIFO_IRQ_THRESHOLD 12 + +PICO_INTERNAL void PicoReratePico(void) +{ + int rate = guessed_rates[PicoPicohw.r12 & 7]; + if (Pico.m.pal) + fifo_bytes_line = (rate<<16)/50/312/2; + else fifo_bytes_line = (rate<<16)/60/262/2; + PicoPicoPCMRerate(rate); +} + +static void PicoLinePico(void) +{ + PicoPicohw.line_counter++; + +#if 1 + if ((PicoPicohw.r12 & 0x4003) && PicoPicohw.line_counter - prev_line_cnt_irq3 > 200) { + prev_line_cnt_irq3 = PicoPicohw.line_counter; + // just a guess/hack, allows 101 Dalmantians to boot + elprintf(EL_PICOHW, "irq3"); + SekInterrupt(3); + return; + } +#endif + + if (PicoPicohw.fifo_bytes > 0) + { + PicoPicohw.fifo_line_bytes += fifo_bytes_line; + if (PicoPicohw.fifo_line_bytes >= (1<<16)) { + PicoPicohw.fifo_bytes -= PicoPicohw.fifo_line_bytes >> 16; + PicoPicohw.fifo_line_bytes &= 0xffff; + if (PicoPicohw.fifo_bytes < 0) + PicoPicohw.fifo_bytes = 0; + } + } + else + PicoPicohw.fifo_line_bytes = 0; + +#if 1 + if (PicoPicohw.fifo_bytes_prev >= PICOHW_FIFO_IRQ_THRESHOLD && + PicoPicohw.fifo_bytes < PICOHW_FIFO_IRQ_THRESHOLD) { + prev_line_cnt_irq3 = PicoPicohw.line_counter; // ? + elprintf(EL_PICOHW, "irq3, fb=%i", PicoPicohw.fifo_bytes); + SekInterrupt(3); + } + PicoPicohw.fifo_bytes_prev = PicoPicohw.fifo_bytes; +#endif + +#if 0 + if (PicoPicohw.line_counter - prev_line_cnt_irq5 > 512) { + prev_line_cnt_irq5 = PicoPicohw.line_counter; + elprintf(EL_PICOHW, "irq5"); + SekInterrupt(5); + } +#endif +} + +static void PicoResetPico(void) +{ + PicoPicoPCMReset(); + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; +} + +PICO_INTERNAL void PicoInitPico(void) +{ + elprintf(EL_STATUS, "Pico startup"); + PicoLineHook = PicoLinePico; + PicoResetHook = PicoResetPico; + + PicoAHW = PAHW_PICO; + memset(&PicoPicohw, 0, sizeof(PicoPicohw)); + PicoPicohw.pen_pos[0] = 0x03c + 320/2; + PicoPicohw.pen_pos[1] = 0x200 + 240/2; + prev_line_cnt_irq3 = prev_line_cnt_irq5 = 0; + + // map version register + PicoDetectRegion(); + switch (Pico.m.hardware >> 6) { + case 0: PicoPicohw.r1 = 0x00; break; + case 1: PicoPicohw.r1 = 0x00; break; + case 2: PicoPicohw.r1 = 0x40; break; + case 3: PicoPicohw.r1 = 0x20; break; + } +} + diff --git a/waterbox/picodrive/pico/pico/xpcm.c b/waterbox/picodrive/pico/pico/xpcm.c new file mode 100644 index 0000000000..0109dcf9fc --- /dev/null +++ b/waterbox/picodrive/pico/pico/xpcm.c @@ -0,0 +1,120 @@ +/* + * PicoDrive + * (C) notaz, 2008 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + * + * The following ADPCM algorithm was stolen from MAME aica driver. + * I'm quite sure it's not the right one, but it's the + * best sounding of the ones that I tried. + */ + +#include "../pico_int.h" + +#define ADPCMSHIFT 8 +#define ADFIX(f) (int) ((double)f * (double)(1< max ) val = max; \ + else if ( val < min ) val = min; \ +} + +static const int TableQuant[8] = +{ + ADFIX(0.8984375), + ADFIX(0.8984375), + ADFIX(0.8984375), + ADFIX(0.8984375), + ADFIX(1.19921875), + ADFIX(1.59765625), + ADFIX(2.0), + ADFIX(2.3984375) +}; + +// changed using trial and error.. +//static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, 15, -1, -3, -5, -7, -9, -11, -13, -15 }; +static const int quant_mul[16] = { 1, 3, 5, 7, 9, 11, 13, -1, -1, -3, -5, -7, -9, -11, -13, -15 }; + +static int sample = 0, quant = 0, sgn = 0; +static int stepsamples = (44100<<10)/16000; + + +PICO_INTERNAL void PicoPicoPCMReset(void) +{ + sample = sgn = 0; + quant = 0x7f; + memset(PicoPicohw.xpcm_buffer, 0, sizeof(PicoPicohw.xpcm_buffer)); +} + +PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate) +{ + stepsamples = (PsndRate<<10)/xpcm_rate; +} + +#define XSHIFT 6 + +#define do_sample() \ +{ \ + int delta = quant * quant_mul[srcval] >> XSHIFT; \ + sample += delta - (delta >> 2); /* 3/4 */ \ + quant = (quant * TableQuant[srcval&7]) >> ADPCMSHIFT; \ + Limit(quant, 0x6000, 0x7f); \ + Limit(sample, 32767*3/4, -32768*3/4); \ +} + +PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo) +{ + unsigned char *src = PicoPicohw.xpcm_buffer; + unsigned char *lim = PicoPicohw.xpcm_ptr; + int srcval, needsamples = 0; + + if (src == lim) goto end; + + for (; length > 0 && src < lim; src++) + { + srcval = *src >> 4; + do_sample(); + + for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) { + *buffer++ += sample; + if (stereo) { buffer[0] = buffer[-1]; buffer++; } + } + + srcval = *src & 0xf; + do_sample(); + + for (needsamples += stepsamples; needsamples > (1<<10) && length > 0; needsamples -= (1<<10), length--) { + *buffer++ += sample; + if (stereo) { buffer[0] = buffer[-1]; buffer++; } + } + + // lame normalization stuff, needed due to wrong adpcm algo + sgn += (sample < 0) ? -1 : 1; + if (sgn < -16 || sgn > 16) sample -= sample >> 5; + } + + if (src < lim) { + int di = lim - src; + memmove(PicoPicohw.xpcm_buffer, src, di); + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer + di; + elprintf(EL_PICOHW, "xpcm update: over %i", di); + // adjust fifo + PicoPicohw.fifo_bytes = di; + return; + } + + elprintf(EL_PICOHW, "xpcm update: under %i", length); + PicoPicohw.xpcm_ptr = PicoPicohw.xpcm_buffer; + +end: + if (stereo) + // still must expand SN76496 to stereo + for (; length > 0; buffer+=2, length--) + buffer[1] = buffer[0]; + + sample = sgn = 0; + quant = 0x7f; +} + diff --git a/waterbox/picodrive/pico/pico_cmn.inc b/waterbox/picodrive/pico/pico_cmn.inc new file mode 100644 index 0000000000..341255a813 --- /dev/null +++ b/waterbox/picodrive/pico/pico_cmn.inc @@ -0,0 +1,290 @@ +/* + * common code for base/cd/32x + * (C) notaz, 2007-2009,2013 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#define CYCLES_M68K_LINE 488 // suitable for both PAL/NTSC +#define CYCLES_M68K_VINT_LAG 68 +#define CYCLES_M68K_ASD 148 + +// pad delay (for 6 button pads) +#define PAD_DELAY() { \ + if(Pico.m.padDelay[0]++ > 25) Pico.m.padTHPhase[0]=0; \ + if(Pico.m.padDelay[1]++ > 25) Pico.m.padTHPhase[1]=0; \ +} + +// CPUS_RUN +#ifndef CPUS_RUN +#define CPUS_RUN(m68k_cycles) \ + SekRunM68k(m68k_cycles) +#endif + +// sync m68k to SekCycleAim +static void SekSyncM68k(void) +{ + int cyc_do; + pprof_start(m68k); + pevt_log_m68k_o(EVT_RUN_START); + + while ((cyc_do = SekCycleAim - SekCycleCnt) > 0) { + SekCycleCnt += cyc_do; + +#if defined(EMU_C68K) + PicoCpuCM68k.cycles = cyc_do; + CycloneRun(&PicoCpuCM68k); + SekCycleCnt -= PicoCpuCM68k.cycles; +#elif defined(EMU_M68K) + SekCycleCnt += m68k_execute(cyc_do) - cyc_do; +#elif defined(EMU_F68K) + SekCycleCnt += fm68k_emulate(cyc_do, 0) - cyc_do; +#endif + } + + SekCyclesLeft = 0; + + SekTrace(0); + pevt_log_m68k_o(EVT_RUN_END); + pprof_end(m68k); +} + +static inline void SekRunM68k(int cyc) +{ + SekCycleAim += cyc; + SekSyncM68k(); +} + +static int PicoFrameHints(void) +{ + struct PicoVideo *pv=&Pico.video; + int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap; + unsigned int cycles; + int hint; // Hint counter + + pevt_log_m68k_o(EVT_FRAME_START); + pv->v_counter = Pico.m.scanline = 0; + + if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled + // draw a frame just after vblank in alternative render mode + // yes, this will cause 1 frame lag, but this is inaccurate mode anyway. + PicoFrameFull(); +#ifdef DRAW_FINISH_FUNC + DRAW_FINISH_FUNC(); +#endif + skip = 1; + } + else skip=PicoSkipFrame; + + if (Pico.m.pal) { + line_sample = 68; + if (pv->reg[1]&8) lines_vis = 240; + } else { + line_sample = 93; + } + + z80_resetCycles(); + PsndDacLine = 0; + emustatus &= ~1; + + pv->status&=~0x88; // clear V-Int, come out of vblank + + hint=pv->reg[10]; // Load H-Int counter + //dprintf("-hint: %i", hint); + + // This is to make active scan longer (needed for Double Dragon 2, mainly) + CPUS_RUN(CYCLES_M68K_ASD); + + for (y = 0; y < lines_vis; y++) + { + pv->v_counter = Pico.m.scanline = y; + if ((pv->reg[12]&6) == 6) { // interlace mode 2 + pv->v_counter <<= 1; + pv->v_counter |= pv->v_counter >> 8; + pv->v_counter &= 0xff; + } + + // VDP FIFO + pv->lwrite_cnt -= 12; + if (pv->lwrite_cnt <= 0) { + pv->lwrite_cnt=0; + Pico.video.status|=0x200; + } + + PAD_DELAY(); + + // H-Interrupts: + if (--hint < 0) // y <= lines_vis: Comix Zone, Golden Axe + { + hint=pv->reg[10]; // Reload H-Int counter + pv->pending_ints|=0x10; + if (pv->reg[0]&0x10) { + elprintf(EL_INTS, "hint: @ %06x [%i]", SekPc, SekCyclesDone()); + SekInterrupt(4); + } + } + + // decide if we draw this line + if (!skip && (PicoOpt & POPT_ALT_RENDERER)) + { + // find the right moment for frame renderer, when display is no longer blanked + if ((pv->reg[1]&0x40) || y > 100) { + PicoFrameFull(); +#ifdef DRAW_FINISH_FUNC + DRAW_FINISH_FUNC(); +#endif + skip = 1; + } + } + + // get samples from sound chips + if ((y == 224 || y == line_sample) && PsndOut) + { + cycles = SekCyclesDone(); + + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) + PicoSyncZ80(cycles); + if (ym2612.dacen && PsndDacLine <= y) + PsndDoDAC(y); +#ifdef PICO_CD + if (PicoAHW & PAHW_MCD) + pcd_sync_s68k(cycles, 0); +#endif +#ifdef PICO_32X + p32x_sync_sh2s(cycles); +#endif + PsndGetSamples(y); + } + + // Run scanline: + line_base_cycles = SekCyclesDone(); + if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + CPUS_RUN(CYCLES_M68K_LINE); + + if (PicoLineHook) PicoLineHook(); + pevt_log_m68k_o(EVT_NEXT_LINE); + } + + if (!skip) + { + if (DrawScanline < y) + PicoDrawSync(y - 1, 0); +#ifdef DRAW_FINISH_FUNC + DRAW_FINISH_FUNC(); +#endif + } + + // V-int line (224 or 240) + Pico.m.scanline = y; + pv->v_counter = 0xe0; // bad for 240 mode + if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1; + + // VDP FIFO + pv->lwrite_cnt=0; + Pico.video.status|=0x200; + + memcpy(PicoPadInt, PicoPad, sizeof(PicoPadInt)); + PAD_DELAY(); + + // Last H-Int: + if (--hint < 0) + { + hint=pv->reg[10]; // Reload H-Int counter + pv->pending_ints|=0x10; + //printf("rhint: %i @ %06x [%i|%i]\n", hint, SekPc, y, SekCyclesDone()); + if (pv->reg[0]&0x10) SekInterrupt(4); + } + + pv->status|=0x08; // go into vblank + pv->pending_ints|=0x20; + + // the following SekRun is there for several reasons: + // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga) + // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants) + // also delay between last H-int and V-int (Golden Axe 3) + line_base_cycles = SekCyclesDone(); + if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + CPUS_RUN(CYCLES_M68K_VINT_LAG); + + if (pv->reg[1]&0x20) { + elprintf(EL_INTS, "vint: @ %06x [%i]", SekPc, SekCyclesDone()); + SekInterrupt(6); + } + + cycles = SekCyclesDone(); + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) { + PicoSyncZ80(cycles); + elprintf(EL_INTS, "zint"); + z80_int(); + } + +#ifdef PICO_CD + if (PicoAHW & PAHW_MCD) + pcd_sync_s68k(cycles, 0); +#endif +#ifdef PICO_32X + p32x_sync_sh2s(cycles); + p32x_start_blank(); +#endif + + // get samples from sound chips + if (y == 224 && PsndOut) + { + if (ym2612.dacen && PsndDacLine <= y) + PsndDoDAC(y); + PsndGetSamples(y); + } + + // Run scanline: + CPUS_RUN(CYCLES_M68K_LINE - CYCLES_M68K_VINT_LAG - CYCLES_M68K_ASD); + + if (PicoLineHook) PicoLineHook(); + pevt_log_m68k_o(EVT_NEXT_LINE); + + lines = scanlines_total; + vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens, TODO: verify + + for (y++; y < lines; y++) + { + pv->v_counter = Pico.m.scanline = y; + if (y >= vcnt_wrap) + pv->v_counter -= Pico.m.pal ? 56 : 6; + if ((pv->reg[12]&6) == 6) + pv->v_counter = (pv->v_counter << 1) | 1; + pv->v_counter &= 0xff; + + PAD_DELAY(); + + // Run scanline: + line_base_cycles = SekCyclesDone(); + if (Pico.m.dma_xfers) SekCyclesBurn(CheckDMA()); + CPUS_RUN(CYCLES_M68K_LINE); + + if (PicoLineHook) PicoLineHook(); + pevt_log_m68k_o(EVT_NEXT_LINE); + } + + // sync cpus + cycles = SekCyclesDone(); + if (Pico.m.z80Run && !Pico.m.z80_reset && (PicoOpt&POPT_EN_Z80)) + PicoSyncZ80(cycles); + if (PsndOut && ym2612.dacen && PsndDacLine <= lines-1) + PsndDoDAC(lines-1); + +#ifdef PICO_CD + if (PicoAHW & PAHW_MCD) + pcd_sync_s68k(cycles, 0); +#endif +#ifdef PICO_32X + p32x_sync_sh2s(cycles); +#endif + timers_cycle(); + + return 0; +} + +#undef PAD_DELAY +#undef CPUS_RUN + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/pico_int.h b/waterbox/picodrive/pico/pico_int.h new file mode 100644 index 0000000000..30bce7bab8 --- /dev/null +++ b/waterbox/picodrive/pico/pico_int.h @@ -0,0 +1,1025 @@ +/* + * PicoDrive - Internal Header File + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#ifndef PICO_INTERNAL_INCLUDED +#define PICO_INTERNAL_INCLUDED + +#include +#include +#include +#include "pico.h" +#include "carthw/carthw.h" + +// +#define USE_POLL_DETECT + +#ifndef PICO_INTERNAL +#define PICO_INTERNAL +#endif +#ifndef PICO_INTERNAL_ASM +#define PICO_INTERNAL_ASM +#endif + +// to select core, define EMU_C68K, EMU_M68K or EMU_F68K in your makefile or project + +#ifdef __cplusplus +extern "C" { +#endif + + +// ----------------------- 68000 CPU ----------------------- +#ifdef EMU_C68K +#include "../cpu/cyclone/Cyclone.h" +extern struct Cyclone PicoCpuCM68k, PicoCpuCS68k; +#define SekCyclesLeft PicoCpuCM68k.cycles // cycles left for this run +#define SekCyclesLeftS68k PicoCpuCS68k.cycles +#define SekPc (PicoCpuCM68k.pc-PicoCpuCM68k.membase) +#define SekPcS68k (PicoCpuCS68k.pc-PicoCpuCS68k.membase) +#define SekDar(x) (x < 8 ? PicoCpuCM68k.d[x] : PicoCpuCM68k.a[x - 8]) +#define SekDarS68k(x) (x < 8 ? PicoCpuCS68k.d[x] : PicoCpuCS68k.a[x - 8]) +#define SekSr CycloneGetSr(&PicoCpuCM68k) +#define SekSrS68k CycloneGetSr(&PicoCpuCS68k) +#define SekSetStop(x) { PicoCpuCM68k.state_flags&=~1; if (x) { PicoCpuCM68k.state_flags|=1; PicoCpuCM68k.cycles=0; } } +#define SekSetStopS68k(x) { PicoCpuCS68k.state_flags&=~1; if (x) { PicoCpuCS68k.state_flags|=1; PicoCpuCS68k.cycles=0; } } +#define SekIsStoppedM68k() (PicoCpuCM68k.state_flags&1) +#define SekIsStoppedS68k() (PicoCpuCS68k.state_flags&1) +#define SekShouldInterrupt() (PicoCpuCM68k.irq > (PicoCpuCM68k.srh&7)) + +#define SekNotPolling PicoCpuCM68k.not_pol +#define SekNotPollingS68k PicoCpuCS68k.not_pol + +#define SekInterrupt(i) PicoCpuCM68k.irq=i +#define SekIrqLevel PicoCpuCM68k.irq + +#endif + +#ifdef EMU_F68K +#include "../cpu/fame/fame.h" +extern M68K_CONTEXT PicoCpuFM68k, PicoCpuFS68k; +#define SekCyclesLeft PicoCpuFM68k.io_cycle_counter +#define SekCyclesLeftS68k PicoCpuFS68k.io_cycle_counter +#define SekPc fm68k_get_pc(&PicoCpuFM68k) +#define SekPcS68k fm68k_get_pc(&PicoCpuFS68k) +#define SekDar(x) (x < 8 ? PicoCpuFM68k.dreg[x].D : PicoCpuFM68k.areg[x - 8].D) +#define SekDarS68k(x) (x < 8 ? PicoCpuFS68k.dreg[x].D : PicoCpuFS68k.areg[x - 8].D) +#define SekSr PicoCpuFM68k.sr +#define SekSrS68k PicoCpuFS68k.sr +#define SekSetStop(x) { \ + PicoCpuFM68k.execinfo &= ~FM68K_HALTED; \ + if (x) { PicoCpuFM68k.execinfo |= FM68K_HALTED; PicoCpuFM68k.io_cycle_counter = 0; } \ +} +#define SekSetStopS68k(x) { \ + PicoCpuFS68k.execinfo &= ~FM68K_HALTED; \ + if (x) { PicoCpuFS68k.execinfo |= FM68K_HALTED; PicoCpuFS68k.io_cycle_counter = 0; } \ +} +#define SekIsStoppedM68k() (PicoCpuFM68k.execinfo&FM68K_HALTED) +#define SekIsStoppedS68k() (PicoCpuFS68k.execinfo&FM68K_HALTED) +#define SekShouldInterrupt() fm68k_would_interrupt() + +#define SekNotPolling PicoCpuFM68k.not_polling +#define SekNotPollingS68k PicoCpuFS68k.not_polling + +#define SekInterrupt(irq) PicoCpuFM68k.interrupts[0]=irq +#define SekIrqLevel PicoCpuFM68k.interrupts[0] + +#endif + +#ifdef EMU_M68K +#include "../cpu/musashi/m68kcpu.h" +extern m68ki_cpu_core PicoCpuMM68k, PicoCpuMS68k; +#ifndef SekCyclesLeft +#define SekCyclesLeft PicoCpuMM68k.cyc_remaining_cycles +#define SekCyclesLeftS68k PicoCpuMS68k.cyc_remaining_cycles +#define SekPc m68k_get_reg(&PicoCpuMM68k, M68K_REG_PC) +#define SekPcS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_PC) +#define SekDar(x) PicoCpuMM68k.dar[x] +#define SekDarS68k(x) PicoCpuMS68k.dar[x] +#define SekSr m68k_get_reg(&PicoCpuMM68k, M68K_REG_SR) +#define SekSrS68k m68k_get_reg(&PicoCpuMS68k, M68K_REG_SR) +#define SekSetStop(x) { \ + if(x) { SET_CYCLES(0); PicoCpuMM68k.stopped=STOP_LEVEL_STOP; } \ + else PicoCpuMM68k.stopped=0; \ +} +#define SekSetStopS68k(x) { \ + if(x) { SET_CYCLES(0); PicoCpuMS68k.stopped=STOP_LEVEL_STOP; } \ + else PicoCpuMS68k.stopped=0; \ +} +#define SekIsStoppedM68k() (PicoCpuMM68k.stopped==STOP_LEVEL_STOP) +#define SekIsStoppedS68k() (PicoCpuMS68k.stopped==STOP_LEVEL_STOP) +#define SekShouldInterrupt() (CPU_INT_LEVEL > FLAG_INT_MASK) + +#define SekNotPolling PicoCpuMM68k.not_polling +#define SekNotPollingS68k PicoCpuMS68k.not_polling + +#define SekInterrupt(irq) { \ + void *oldcontext = m68ki_cpu_p; \ + m68k_set_context(&PicoCpuMM68k); \ + m68k_set_irq(irq); \ + m68k_set_context(oldcontext); \ +} +#define SekIrqLevel (PicoCpuMM68k.int_level >> 8) + +#endif +#endif // EMU_M68K + +// while running, cnt represents target of current timeslice +// while not in SekRun(), it's actual cycles done +// (but always use SekCyclesDone() if you need current position) +// cnt may change if timeslice is ended prematurely or extended, +// so we use SekCycleAim for the actual target +extern unsigned int SekCycleCnt; +extern unsigned int SekCycleAim; + +// number of cycles done (can be checked anywhere) +#define SekCyclesDone() (SekCycleCnt - SekCyclesLeft) + +// burn cycles while not in SekRun() and while in +#define SekCyclesBurn(c) SekCycleCnt += c +#define SekCyclesBurnRun(c) { \ + SekCyclesLeft -= c; \ +} + +// note: sometimes may extend timeslice to delay an irq +#define SekEndRun(after) { \ + SekCycleCnt -= SekCyclesLeft - (after); \ + SekCyclesLeft = after; \ +} + +extern unsigned int SekCycleCntS68k; +extern unsigned int SekCycleAimS68k; + +#define SekEndRunS68k(after) { \ + if (SekCyclesLeftS68k > (after)) { \ + SekCycleCntS68k -= SekCyclesLeftS68k - (after); \ + SekCyclesLeftS68k = after; \ + } \ +} + +#define SekCyclesDoneS68k() (SekCycleCntS68k - SekCyclesLeftS68k) + +// compare cycles, handling overflows +// check if a > b +#define CYCLES_GT(a, b) \ + ((int)((a) - (b)) > 0) +// check if a >= b +#define CYCLES_GE(a, b) \ + ((int)((a) - (b)) >= 0) + +// ----------------------- Z80 CPU ----------------------- + +#if defined(_USE_DRZ80) +#include "../cpu/DrZ80/drz80.h" + +extern struct DrZ80 drZ80; + +#define z80_run(cycles) ((cycles) - DrZ80Run(&drZ80, cycles)) +#define z80_run_nr(cycles) DrZ80Run(&drZ80, cycles) +#define z80_int() drZ80.Z80_IRQ = 1 +#define z80_int() drZ80.Z80_IRQ = 1 +#define z80_nmi() drZ80.Z80IF |= 8 + +#define z80_cyclesLeft drZ80.cycles +#define z80_pc() (drZ80.Z80PC - drZ80.Z80PC_BASE) + +#elif defined(_USE_CZ80) +#include "../cpu/cz80/cz80.h" + +#define z80_run(cycles) Cz80_Exec(&CZ80, cycles) +#define z80_run_nr(cycles) Cz80_Exec(&CZ80, cycles) +#define z80_int() Cz80_Set_IRQ(&CZ80, 0, HOLD_LINE) +#define z80_nmi() Cz80_Set_IRQ(&CZ80, IRQ_LINE_NMI, 0) + +#define z80_cyclesLeft (CZ80.ICount - CZ80.ExtraCycles) +#define z80_pc() Cz80_Get_Reg(&CZ80, CZ80_PC) + +#else + +#define z80_run(cycles) (cycles) +#define z80_run_nr(cycles) +#define z80_int() +#define z80_nmi() + +#endif + +#define Z80_STATE_SIZE 0x60 + +extern unsigned int last_z80_sync; +extern int z80_cycle_cnt; /* 'done' z80 cycles before z80_run() */ +extern int z80_cycle_aim; +extern int z80_scanline; +extern int z80_scanline_cycles; /* cycles done until z80_scanline */ + +#define z80_resetCycles() \ + last_z80_sync = SekCyclesDone(); \ + z80_cycle_cnt = z80_cycle_aim = z80_scanline = z80_scanline_cycles = 0; + +#define z80_cyclesDone() \ + (z80_cycle_aim - z80_cyclesLeft) + +#define cycles_68k_to_z80(x) ((x)*957 >> 11) + +// ----------------------- SH2 CPU ----------------------- + +#include "cpu/sh2/sh2.h" + +extern SH2 sh2s[2]; +#define msh2 sh2s[0] +#define ssh2 sh2s[1] + +#ifndef DRC_SH2 +# define sh2_end_run(sh2, after_) do { \ + if ((sh2)->icount > (after_)) { \ + (sh2)->cycles_timeslice -= (sh2)->icount - (after_); \ + (sh2)->icount = after_; \ + } \ +} while (0) +# define sh2_cycles_left(sh2) (sh2)->icount +# define sh2_burn_cycles(sh2, n) (sh2)->icount -= n +# define sh2_pc(sh2) (sh2)->ppc +#else +# define sh2_end_run(sh2, after_) do { \ + int left_ = (signed int)(sh2)->sr >> 12; \ + if (left_ > (after_)) { \ + (sh2)->cycles_timeslice -= left_ - (after_); \ + (sh2)->sr &= 0xfff; \ + (sh2)->sr |= (after_) << 12; \ + } \ +} while (0) +# define sh2_cycles_left(sh2) ((signed int)(sh2)->sr >> 12) +# define sh2_burn_cycles(sh2, n) (sh2)->sr -= ((n) << 12) +# define sh2_pc(sh2) (sh2)->pc +#endif + +#define sh2_cycles_done(sh2) ((int)(sh2)->cycles_timeslice - sh2_cycles_left(sh2)) +#define sh2_cycles_done_t(sh2) \ + ((sh2)->m68krcycles_done * 3 + sh2_cycles_done(sh2)) +#define sh2_cycles_done_m68k(sh2) \ + ((sh2)->m68krcycles_done + (sh2_cycles_done(sh2) / 3)) + +#define sh2_reg(c, x) (c) ? ssh2.r[x] : msh2.r[x] +#define sh2_gbr(c) (c) ? ssh2.gbr : msh2.gbr +#define sh2_vbr(c) (c) ? ssh2.vbr : msh2.vbr +#define sh2_sr(c) (((c) ? ssh2.sr : msh2.sr) & 0xfff) + +#define sh2_set_gbr(c, v) \ + { if (c) ssh2.gbr = v; else msh2.gbr = v; } +#define sh2_set_vbr(c, v) \ + { if (c) ssh2.vbr = v; else msh2.vbr = v; } + +#define elprintf_sh2(sh2, w, f, ...) \ + elprintf(w,"%csh2 "f,(sh2)->is_slave?'s':'m',##__VA_ARGS__) + +// --------------------------------------------------------- + +// main oscillator clock which controls timing +#define OSC_NTSC 53693100 +#define OSC_PAL 53203424 + +struct PicoVideo +{ + unsigned char reg[0x20]; + unsigned int command; // 32-bit Command + unsigned char pending; // 1 if waiting for second half of 32-bit command + unsigned char type; // Command type (v/c/vsram read/write) + unsigned short addr; // Read/Write address + int status; // Status bits + unsigned char pending_ints; // pending interrupts: ??VH???? + signed char lwrite_cnt; // VDP write count during active display line + unsigned short v_counter; // V-counter + unsigned char pad[0x10]; +}; + +struct PicoMisc +{ + unsigned char rotate; + unsigned char z80Run; + unsigned char padTHPhase[2]; // 02 phase of gamepad TH switches + unsigned short scanline; // 04 0 to 261||311 + char dirtyPal; // 06 Is the palette dirty (1 - change @ this frame, 2 - some time before) + unsigned char hardware; // 07 Hardware value for country + unsigned char pal; // 08 1=PAL 0=NTSC + unsigned char sram_reg; // 09 SRAM reg. See SRR_* below + unsigned short z80_bank68k; // 0a + unsigned short pad0; + unsigned char ncart_in; // 0e !cart_in + unsigned char z80_reset; // 0f z80 reset held + unsigned char padDelay[2]; // 10 gamepad phase time outs, so we count a delay + unsigned short eeprom_addr; // EEPROM address register + unsigned char eeprom_cycle; // EEPROM cycle number + unsigned char eeprom_slave; // EEPROM slave word for X24C02 and better SRAMs + unsigned char eeprom_status; + unsigned char pad2; + unsigned short dma_xfers; // 18 + unsigned char eeprom_wb[2]; // EEPROM latch/write buffer + unsigned int frame_count; // 1c for movies and idle det +}; + +struct PicoMS +{ + unsigned char carthw[0x10]; + unsigned char io_ctl; + unsigned char nmi_state; + unsigned char pad[0x4e]; +}; + +// some assembly stuff depend on these, do not touch! +struct Pico +{ + unsigned char ram[0x10000]; // 0x00000 scratch ram + union { // vram is byteswapped for easier reads when drawing + unsigned short vram[0x8000]; // 0x10000 + unsigned char vramb[0x4000]; // VRAM in SMS mode + }; + unsigned char zram[0x2000]; // 0x20000 Z80 ram + unsigned char ioports[0x10]; // XXX: fix asm and mv + unsigned char pad[0xf0]; // unused + unsigned short cram[0x40]; // 0x22100 + unsigned short vsram[0x40]; // 0x22180 + + unsigned char *rom; // 0x22200 + unsigned int romsize; // 0x22204 (on 32bits) + + struct PicoMisc m; + struct PicoVideo video; + struct PicoMS ms; +}; + +// sram +#define SRR_MAPPED (1 << 0) +#define SRR_READONLY (1 << 1) + +#define SRF_ENABLED (1 << 0) +#define SRF_EEPROM (1 << 1) + +struct PicoSRAM +{ + unsigned char *data; // actual data + unsigned int start; // start address in 68k address space + unsigned int end; + unsigned char flags; // 0c: SRF_* + unsigned char unused2; + unsigned char changed; + unsigned char eeprom_type; // eeprom type: 0: 7bit (24C01), 2: 2 addr words (X24C02+), 3: 3 addr words + unsigned char unused3; + unsigned char eeprom_bit_cl; // bit number for cl + unsigned char eeprom_bit_in; // bit number for in + unsigned char eeprom_bit_out; // bit number for out + unsigned int size; +}; + +// MCD +#define PCM_MIXBUF_LEN ((12500000 / 384) / 50 + 1) + +struct mcd_pcm +{ + unsigned char control; // reg7 + unsigned char enabled; // reg8 + unsigned char cur_ch; + unsigned char bank; + unsigned int update_cycles; + + struct pcm_chan // 08, size 0x10 + { + unsigned char regs[8]; + unsigned int addr; // .08: played sample address + int pad; + } ch[8]; +}; + +#define PCD_ST_S68K_RST 1 + +struct mcd_misc +{ + unsigned short hint_vector; + unsigned char busreq; // not s68k_regs[1] + unsigned char s68k_pend_ints; + unsigned int state_flags; // 04 + unsigned int stopwatch_base_c; + unsigned short m68k_poll_a; + unsigned short m68k_poll_cnt; + unsigned short s68k_poll_a; + unsigned short s68k_poll_cnt; + unsigned int s68k_poll_clk; + unsigned char bcram_reg; // 18: battery-backed RAM cart register + unsigned char dmna_ret_2m; + unsigned char need_sync; + unsigned char pad3; + int pad4[9]; +}; + +typedef struct +{ + unsigned char bios[0x20000]; // 000000: 128K + union { // 020000: 512K + unsigned char prg_ram[0x80000]; + unsigned char prg_ram_b[4][0x20000]; + }; + union { // 0a0000: 256K + struct { + unsigned char word_ram2M[0x40000]; + unsigned char unused0[0x20000]; + }; + struct { + unsigned char unused1[0x20000]; + unsigned char word_ram1M[2][0x20000]; + }; + }; + union { // 100000: 64K + unsigned char pcm_ram[0x10000]; + unsigned char pcm_ram_b[0x10][0x1000]; + }; + unsigned char s68k_regs[0x200]; // 110000: GA, not CPU regs + unsigned char bram[0x2000]; // 110200: 8K + struct mcd_misc m; // 112200: misc + struct mcd_pcm pcm; // 112240: + void *cdda_stream; + int cdda_type; + int pcm_mixbuf[PCM_MIXBUF_LEN * 2]; + int pcm_mixpos; + char pcm_mixbuf_dirty; + char pcm_regs_dirty; +} mcd_state; + +// XXX: this will need to be reworked for cart+cd support. +#define Pico_mcd ((mcd_state *)Pico.rom) + +// 32X +#define P32XS_FM (1<<15) +#define P32XS_nCART (1<< 8) +#define P32XS_REN (1<< 7) +#define P32XS_nRES (1<< 1) +#define P32XS_ADEN (1<< 0) +#define P32XS2_ADEN (1<< 9) +#define P32XS_FULL (1<< 7) // DREQ FIFO full +#define P32XS_68S (1<< 2) +#define P32XS_DMA (1<< 1) +#define P32XS_RV (1<< 0) + +#define P32XV_nPAL (1<<15) // VDP +#define P32XV_PRI (1<< 7) +#define P32XV_Mx (3<< 0) // display mode mask + +#define P32XV_SFT (1<< 0) + +#define P32XV_VBLK (1<<15) +#define P32XV_HBLK (1<<14) +#define P32XV_PEN (1<<13) +#define P32XV_nFEN (1<< 1) +#define P32XV_FS (1<< 0) + +#define P32XP_RTP (1<<7) // PWM control +#define P32XP_FULL (1<<15) // PWM pulse +#define P32XP_EMPTY (1<<14) + +#define P32XF_68KCPOLL (1 << 0) +#define P32XF_68KVPOLL (1 << 1) +#define P32XF_Z80_32X_IO (1 << 7) // z80 does 32x io + +#define P32XI_VRES (1 << 14/2) // IRL/2 +#define P32XI_VINT (1 << 12/2) +#define P32XI_HINT (1 << 10/2) +#define P32XI_CMD (1 << 8/2) +#define P32XI_PWM (1 << 6/2) + +// peripheral reg access +#define PREG8(regs,offs) ((unsigned char *)regs)[offs ^ 3] + +#define DMAC_FIFO_LEN (4*2) +#define PWM_BUFF_LEN 1024 // in one channel samples + +#define SH2_DRCBLK_RAM_SHIFT 1 +#define SH2_DRCBLK_DA_SHIFT 1 + +#define SH2_READ_SHIFT 25 +#define SH2_WRITE_SHIFT 25 + +struct Pico32x +{ + unsigned short regs[0x20]; + unsigned short vdp_regs[0x10]; // 0x40 + unsigned short sh2_regs[3]; // 0x60 + unsigned char pending_fb; + unsigned char dirty_pal; + unsigned int emu_flags; + unsigned char sh2irq_mask[2]; + unsigned char sh2irqi[2]; // individual + unsigned int sh2irqs; // common irqs + unsigned short dmac_fifo[DMAC_FIFO_LEN]; + unsigned int pad[4]; + unsigned int dmac0_fifo_ptr; + unsigned short vdp_fbcr_fake; + unsigned short pad2; + unsigned char comm_dirty_68k; + unsigned char comm_dirty_sh2; + unsigned char pwm_irq_cnt; + unsigned char pad1; + unsigned short pwm_p[2]; // pwm pos in fifo + unsigned int pwm_cycle_p; // pwm play cursor (32x cycles) + unsigned int reserved[6]; +}; + +struct Pico32xMem +{ + unsigned char sdram[0x40000]; +#ifdef DRC_SH2 + unsigned short drcblk_ram[1 << (18 - SH2_DRCBLK_RAM_SHIFT)]; +#endif + unsigned short dram[2][0x20000/2]; // AKA fb + union { + unsigned char m68k_rom[0x100]; + unsigned char m68k_rom_bank[0x10000]; // M68K_BANK_SIZE + }; +#ifdef DRC_SH2 + unsigned short drcblk_da[2][1 << (12 - SH2_DRCBLK_DA_SHIFT)]; +#endif + union { + unsigned char b[0x800]; + unsigned short w[0x800/2]; + } sh2_rom_m; + union { + unsigned char b[0x400]; + unsigned short w[0x400/2]; + } sh2_rom_s; + unsigned short pal[0x100]; + unsigned short pal_native[0x100]; // converted to native (for renderer) + signed short pwm[2*PWM_BUFF_LEN]; // PWM buffer for current frame + signed short pwm_current[2]; // current converted samples + unsigned short pwm_fifo[2][4]; // [0] - current raw, others - fifo entries +}; + +// cart.c +extern int PicoCartResize(int newsize); +extern void Byteswap(void *dst, const void *src, int len); +extern void (*PicoCartMemSetup)(void); + +// debug.c +int CM_compareRun(int cyc, int is_sub); + +// draw.c +PICO_INTERNAL void PicoFrameStart(void); +void PicoDrawSync(int to, int blank_last_line); +void BackFill(int reg7, int sh); +void FinalizeLine555(int sh, int line); +extern int (*PicoScanBegin)(unsigned int num); +extern int (*PicoScanEnd)(unsigned int num); +extern int DrawScanline; +#define MAX_LINE_SPRITES 29 +extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES]; +extern void *DrawLineDestBase; +extern int DrawLineDestIncrement; + +// draw2.c +PICO_INTERNAL void PicoFrameFull(); + +// mode4.c +void PicoFrameStartMode4(void); +void PicoLineMode4(int line); +void PicoDoHighPal555M4(void); +void PicoDrawSetOutputMode4(pdso_t which); + +// memory.c +PICO_INTERNAL void PicoMemSetup(void); +unsigned int PicoRead8_io(unsigned int a); +unsigned int PicoRead16_io(unsigned int a); +void PicoWrite8_io(unsigned int a, unsigned int d); +void PicoWrite16_io(unsigned int a, unsigned int d); + +// pico/memory.c +PICO_INTERNAL void PicoMemSetupPico(void); + +// cd/cdc.c +void cdc_init(void); +void cdc_reset(void); +int cdc_context_save(unsigned char *state); +int cdc_context_load(unsigned char *state); +int cdc_context_load_old(unsigned char *state); +void cdc_dma_update(void); +int cdc_decoder_update(unsigned char header[4]); +void cdc_reg_w(unsigned char data); +unsigned char cdc_reg_r(void); +unsigned short cdc_host_r(void); + +// cd/cdd.c +void cdd_reset(void); +int cdd_context_save(unsigned char *state); +int cdd_context_load(unsigned char *state); +int cdd_context_load_old(unsigned char *state); +void cdd_read_data(unsigned char *dst); +void cdd_read_audio(unsigned int samples); +void cdd_update(void); +void cdd_process(void); + +// cd/cd_image.c +int load_cd_image(const char *cd_img_name, int *type); + +// cd/gfx.c +void gfx_init(void); +void gfx_start(unsigned int base); +void gfx_update(unsigned int cycles); +int gfx_context_save(unsigned char *state); +int gfx_context_load(const unsigned char *state); + +// cd/gfx_dma.c +void DmaSlowCell(unsigned int source, unsigned int a, int len, unsigned char inc); + +// cd/memory.c +PICO_INTERNAL void PicoMemSetupCD(void); +unsigned int PicoRead8_mcd_io(unsigned int a); +unsigned int PicoRead16_mcd_io(unsigned int a); +void PicoWrite8_mcd_io(unsigned int a, unsigned int d); +void PicoWrite16_mcd_io(unsigned int a, unsigned int d); +void pcd_state_loaded_mem(void); + +// pico.c +extern struct Pico Pico; +extern struct PicoSRAM SRam; +extern int PicoPadInt[2]; +extern int emustatus; +extern int scanlines_total; +extern void (*PicoResetHook)(void); +extern void (*PicoLineHook)(void); +PICO_INTERNAL int CheckDMA(void); +PICO_INTERNAL void PicoDetectRegion(void); +PICO_INTERNAL void PicoSyncZ80(unsigned int m68k_cycles_done); + +// cd/mcd.c +#define PCDS_IEN1 (1<<1) +#define PCDS_IEN2 (1<<2) +#define PCDS_IEN3 (1<<3) +#define PCDS_IEN4 (1<<4) +#define PCDS_IEN5 (1<<5) +#define PCDS_IEN6 (1<<6) + +PICO_INTERNAL void PicoInitMCD(void); +PICO_INTERNAL void PicoExitMCD(void); +PICO_INTERNAL void PicoPowerMCD(void); +PICO_INTERNAL int PicoResetMCD(void); +PICO_INTERNAL void PicoFrameMCD(void); + +enum pcd_event { + PCD_EVENT_CDC, + PCD_EVENT_TIMER3, + PCD_EVENT_GFX, + PCD_EVENT_DMA, + PCD_EVENT_COUNT, +}; +extern unsigned int pcd_event_times[PCD_EVENT_COUNT]; +void pcd_event_schedule(unsigned int now, enum pcd_event event, int after); +void pcd_event_schedule_s68k(enum pcd_event event, int after); +void pcd_prepare_frame(void); +unsigned int pcd_cycles_m68k_to_s68k(unsigned int c); +int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync); +void pcd_run_cpus(int m68k_cycles); +void pcd_soft_reset(void); +void pcd_state_loaded(void); + +// cd/pcm.c +void pcd_pcm_sync(unsigned int to); +void pcd_pcm_update(int *buffer, int length, int stereo); +void pcd_pcm_write(unsigned int a, unsigned int d); +unsigned int pcd_pcm_read(unsigned int a); + +// pico/pico.c +PICO_INTERNAL void PicoInitPico(void); +PICO_INTERNAL void PicoReratePico(void); + +// pico/xpcm.c +PICO_INTERNAL void PicoPicoPCMUpdate(short *buffer, int length, int stereo); +PICO_INTERNAL void PicoPicoPCMReset(void); +PICO_INTERNAL void PicoPicoPCMRerate(int xpcm_rate); + +// sek.c +PICO_INTERNAL void SekInit(void); +PICO_INTERNAL int SekReset(void); +PICO_INTERNAL void SekState(int *data); +PICO_INTERNAL void SekSetRealTAS(int use_real); +PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub); +PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub); +void SekStepM68k(void); +void SekInitIdleDet(void); +void SekFinishIdleDet(void); +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +void SekTrace(int is_s68k); +#else +#define SekTrace(x) +#endif + +// cd/sek.c +PICO_INTERNAL void SekInitS68k(void); +PICO_INTERNAL int SekResetS68k(void); +PICO_INTERNAL int SekInterruptS68k(int irq); +void SekInterruptClearS68k(int irq); + +// sound/sound.c +extern short cdda_out_buffer[2*1152]; +extern int PsndLen_exc_cnt; +extern int PsndLen_exc_add; +extern int timer_a_next_oflow, timer_a_step; // in z80 cycles +extern int timer_b_next_oflow, timer_b_step; + +void cdda_start_play(int lba_base, int lba_offset, int lb_len); + +void ym2612_sync_timers(int z80_cycles, int mode_old, int mode_new); +void ym2612_pack_state(void); +void ym2612_unpack_state(void); + +#define TIMER_NO_OFLOW 0x70000000 +// tA = 72 * (1024 - NA) / M +#define TIMER_A_TICK_ZCYCLES 17203 +// tB = 1152 * (256 - NA) / M +#define TIMER_B_TICK_ZCYCLES 262800 // 275251 broken, see Dai Makaimura + +#define timers_cycle() \ + if (timer_a_next_oflow > 0 && timer_a_next_oflow < TIMER_NO_OFLOW) \ + timer_a_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ + if (timer_b_next_oflow > 0 && timer_b_next_oflow < TIMER_NO_OFLOW) \ + timer_b_next_oflow -= Pico.m.pal ? 70938*256 : 59659*256; \ + ym2612_sync_timers(0, ym2612.OPN.ST.mode, ym2612.OPN.ST.mode); + +#define timers_reset() \ + timer_a_next_oflow = timer_b_next_oflow = TIMER_NO_OFLOW; \ + timer_a_step = TIMER_A_TICK_ZCYCLES * 1024; \ + timer_b_step = TIMER_B_TICK_ZCYCLES * 256; + + +// videoport.c +extern int line_base_cycles; +PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d); +PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a); +PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a); +extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp); + +// misc.c +PICO_INTERNAL_ASM void memcpy16(unsigned short *dest, unsigned short *src, int count); +PICO_INTERNAL_ASM void memcpy16bswap(unsigned short *dest, void *src, int count); +PICO_INTERNAL_ASM void memcpy32(void *dest, const void *src, int count); // 32bit word count +PICO_INTERNAL_ASM void memset32(void *dest, int c, int count); + +// eeprom.c +void EEPROM_write8(unsigned int a, unsigned int d); +void EEPROM_write16(unsigned int d); +unsigned int EEPROM_read(void); + +// z80 functionality wrappers +PICO_INTERNAL void z80_init(void); +PICO_INTERNAL void z80_pack(void *data); +PICO_INTERNAL int z80_unpack(const void *data); +PICO_INTERNAL void z80_reset(void); +PICO_INTERNAL void z80_exit(void); + +// cd/misc.c +PICO_INTERNAL_ASM void wram_2M_to_1M(unsigned char *m); +PICO_INTERNAL_ASM void wram_1M_to_2M(unsigned char *m); + +// sound/sound.c +PICO_INTERNAL void PsndReset(void); +PICO_INTERNAL void PsndDoDAC(int line_to); +PICO_INTERNAL void PsndClear(void); +PICO_INTERNAL void PsndGetSamples(int y); +PICO_INTERNAL void PsndGetSamplesMS(void); +extern int PsndDacLine; + +// sms.c +#ifndef NO_SMS +void PicoPowerMS(void); +void PicoResetMS(void); +void PicoMemSetupMS(void); +void PicoStateLoadedMS(void); +void PicoFrameMS(void); +void PicoFrameDrawOnlyMS(void); +#else +#define PicoPowerMS() +#define PicoResetMS() +#define PicoMemSetupMS() +#define PicoStateLoadedMS() +#define PicoFrameMS() +#define PicoFrameDrawOnlyMS() +#endif + +// 32x/32x.c +#ifndef NO_32X +extern struct Pico32x Pico32x; +enum p32x_event { + P32X_EVENT_PWM, + P32X_EVENT_FILLEND, + P32X_EVENT_HINT, + P32X_EVENT_COUNT, +}; +extern unsigned int p32x_event_times[P32X_EVENT_COUNT]; + +void Pico32xInit(void); +void PicoPower32x(void); +void PicoReset32x(void); +void Pico32xStartup(void); +void PicoFrame32x(void); +void p32x_sync_sh2s(unsigned int m68k_target); +void p32x_sync_other_sh2(SH2 *sh2, unsigned int m68k_target); +void p32x_update_irls(SH2 *active_sh2, int m68k_cycles); +void p32x_trigger_irq(SH2 *sh2, int m68k_cycles, unsigned int mask); +void p32x_update_cmd_irq(SH2 *sh2, int m68k_cycles); +void p32x_reset_sh2s(void); +void p32x_event_schedule(unsigned int now, enum p32x_event event, int after); +void p32x_event_schedule_sh2(SH2 *sh2, enum p32x_event event, int after); +void p32x_schedule_hint(SH2 *sh2, int m68k_cycles); + +// 32x/memory.c +struct Pico32xMem *Pico32xMem; +unsigned int PicoRead8_32x(unsigned int a); +unsigned int PicoRead16_32x(unsigned int a); +void PicoWrite8_32x(unsigned int a, unsigned int d); +void PicoWrite16_32x(unsigned int a, unsigned int d); +void PicoMemSetup32x(void); +void Pico32xSwapDRAM(int b); +void p32x_m68k_poll_event(unsigned int flags); +void p32x_sh2_poll_event(SH2 *sh2, unsigned int flags, unsigned int m68k_cycles); + +// 32x/draw.c +void PicoDrawSetOutFormat32x(pdso_t which, int use_32x_line_mode); +void FinalizeLine32xRGB555(int sh, int line); +void PicoDraw32xLayer(int offs, int lines, int mdbg); +void PicoDraw32xLayerMdOnly(int offs, int lines); +extern int (*PicoScan32xBegin)(unsigned int num); +extern int (*PicoScan32xEnd)(unsigned int num); +enum { + PDM32X_OFF, + PDM32X_32X_ONLY, + PDM32X_BOTH, +}; +extern int Pico32xDrawMode; + +// 32x/pwm.c +unsigned int p32x_pwm_read16(unsigned int a, SH2 *sh2, + unsigned int m68k_cycles); +void p32x_pwm_write16(unsigned int a, unsigned int d, + SH2 *sh2, unsigned int m68k_cycles); +void p32x_pwm_update(int *buf32, int length, int stereo); +void p32x_pwm_ctl_changed(void); +void p32x_pwm_schedule(unsigned int m68k_now); +void p32x_pwm_schedule_sh2(SH2 *sh2); +void p32x_pwm_sync_to_sh2(SH2 *sh2); +void p32x_pwm_irq_event(unsigned int m68k_now); +void p32x_pwm_state_loaded(void); + +// 32x/sh2soc.c +void p32x_dreq0_trigger(void); +void p32x_dreq1_trigger(void); +void p32x_timers_recalc(void); +void p32x_timers_do(unsigned int m68k_slice); +void sh2_peripheral_reset(SH2 *sh2); +unsigned int sh2_peripheral_read8(unsigned int a, SH2 *sh2); +unsigned int sh2_peripheral_read16(unsigned int a, SH2 *sh2); +unsigned int sh2_peripheral_read32(unsigned int a, SH2 *sh2); +void REGPARM(3) sh2_peripheral_write8(unsigned int a, unsigned int d, SH2 *sh2); +void REGPARM(3) sh2_peripheral_write16(unsigned int a, unsigned int d, SH2 *sh2); +void REGPARM(3) sh2_peripheral_write32(unsigned int a, unsigned int d, SH2 *sh2); + +#else +#define Pico32xInit() +#define PicoPower32x() +#define PicoReset32x() +#define PicoFrame32x() +#define Pico32xStateLoaded() +#define FinalizeLine32xRGB555 NULL +#define p32x_pwm_update(...) +#define p32x_timers_recalc() +#endif + +/* avoid dependency on newer glibc */ +static __inline int isspace_(int c) +{ + return (0x09 <= c && c <= 0x0d) || c == ' '; +} + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#endif + +// emulation event logging +#ifndef EL_LOGMASK +# ifdef __x86_64__ // HACK +# define EL_LOGMASK (EL_STATUS|EL_IDLE|EL_ANOMALY) +# else +# define EL_LOGMASK (EL_STATUS) +# endif +#endif + +#define EL_HVCNT 0x00000001 /* hv counter reads */ +#define EL_SR 0x00000002 /* SR reads */ +#define EL_INTS 0x00000004 /* ints and acks */ +#define EL_YMTIMER 0x00000008 /* ym2612 timer stuff */ +#define EL_INTSW 0x00000010 /* log irq switching on/off */ +#define EL_ASVDP 0x00000020 /* VDP accesses during active scan */ +#define EL_VDPDMA 0x00000040 /* VDP DMA transfers and their timing */ +#define EL_BUSREQ 0x00000080 /* z80 busreq r/w or reset w */ +#define EL_Z80BNK 0x00000100 /* z80 i/o through bank area */ +#define EL_SRAMIO 0x00000200 /* sram i/o */ +#define EL_EEPROM 0x00000400 /* eeprom debug */ +#define EL_UIO 0x00000800 /* unmapped i/o */ +#define EL_IO 0x00001000 /* all i/o */ +#define EL_CDPOLL 0x00002000 /* MCD: log poll detection */ +#define EL_SVP 0x00004000 /* SVP stuff */ +#define EL_PICOHW 0x00008000 /* Pico stuff */ +#define EL_IDLE 0x00010000 /* idle loop det. */ +#define EL_CDREGS 0x00020000 /* MCD: register access */ +#define EL_CDREG3 0x00040000 /* MCD: register 3 only */ +#define EL_32X 0x00080000 +#define EL_PWM 0x00100000 /* 32X PWM stuff (LOTS of output) */ +#define EL_32XP 0x00200000 /* 32X peripherals */ +#define EL_CD 0x00400000 /* MCD */ + +#define EL_STATUS 0x40000000 /* status messages */ +#define EL_ANOMALY 0x80000000 /* some unexpected conditions (during emulation) */ + +#if EL_LOGMASK +#define elprintf(w,f,...) \ +do { \ + if ((w) & EL_LOGMASK) \ + lprintf("%05i:%03i: " f "\n",Pico.m.frame_count,Pico.m.scanline,##__VA_ARGS__); \ +} while (0) +#elif defined(_MSC_VER) +#define elprintf +#else +#define elprintf(w,f,...) +#endif + +// profiling +#ifdef PPROF +#include +#else +#define pprof_init() +#define pprof_finish() +#define pprof_start(x) +#define pprof_end(...) +#define pprof_end_sub(...) +#endif + +#ifdef EVT_LOG +enum evt { + EVT_FRAME_START, + EVT_NEXT_LINE, + EVT_RUN_START, + EVT_RUN_END, + EVT_POLL_START, + EVT_POLL_END, + EVT_CNT +}; + +enum evt_cpu { + EVT_M68K, + EVT_S68K, + EVT_MSH2, + EVT_SSH2, + EVT_CPU_CNT +}; + +void pevt_log(unsigned int cycles, enum evt_cpu c, enum evt e); +void pevt_dump(void); + +#define pevt_log_m68k(e) \ + pevt_log(SekCyclesDone(), EVT_M68K, e) +#define pevt_log_m68k_o(e) \ + pevt_log(SekCyclesDone(), EVT_M68K, e) +#define pevt_log_sh2(sh2, e) \ + pevt_log(sh2_cycles_done_m68k(sh2), EVT_MSH2 + (sh2)->is_slave, e) +#define pevt_log_sh2_o(sh2, e) \ + pevt_log((sh2)->m68krcycles_done, EVT_MSH2 + (sh2)->is_slave, e) +#else +#define pevt_log(c, e) +#define pevt_log_m68k(e) +#define pevt_log_m68k_o(e) +#define pevt_log_sh2(sh2, e) +#define pevt_log_sh2_o(sh2, e) +#define pevt_dump() +#endif + +// misc +#ifdef _MSC_VER +#define cdprintf +#else +#define cdprintf(x...) +#endif + +#if defined(__GNUC__) && defined(__i386__) +#define REGPARM(x) __attribute__((regparm(x))) +#else +#define REGPARM(x) +#endif + +#ifdef __GNUC__ +#define NOINLINE __attribute__((noinline)) +#else +#define NOINLINE +#endif + +#ifdef __cplusplus +} // End of extern "C" +#endif + +#endif // PICO_INTERNAL_INCLUDED + diff --git a/waterbox/picodrive/pico/sek.c b/waterbox/picodrive/pico/sek.c new file mode 100644 index 0000000000..86a351f64a --- /dev/null +++ b/waterbox/picodrive/pico/sek.c @@ -0,0 +1,589 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2009 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" +#include "memory.h" + + +unsigned int SekCycleCnt; +unsigned int SekCycleAim; + + +/* context */ +// Cyclone 68000 +#ifdef EMU_C68K +struct Cyclone PicoCpuCM68k; +#endif +// MUSASHI 68000 +#ifdef EMU_M68K +m68ki_cpu_core PicoCpuMM68k; +#endif +// FAME 68000 +#ifdef EMU_F68K +M68K_CONTEXT PicoCpuFM68k; +#endif + + +/* callbacks */ +#ifdef EMU_C68K +// interrupt acknowledgment +static int SekIntAck(int level) +{ + // try to emulate VDP's reaction to 68000 int ack + if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCycleCnt); } + else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCycleCnt); } + PicoCpuCM68k.irq = 0; + return CYCLONE_INT_ACK_AUTOVECTOR; +} + +static void SekResetAck(void) +{ + elprintf(EL_ANOMALY, "Reset encountered @ %06x", SekPc); +} + +static int SekUnrecognizedOpcode() +{ + unsigned int pc; + pc = SekPc; + elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", pc); + // see if we are still in a mapped region + pc &= 0x00ffffff; + if (map_flag_set(m68k_read16_map[pc >> M68K_MEM_SHIFT])) { + elprintf(EL_STATUS|EL_ANOMALY, "m68k crash @%06x", pc); + PicoCpuCM68k.cycles = 0; + PicoCpuCM68k.state_flags |= 1; + return 1; + } +#ifdef EMU_M68K // debugging cyclone + { + extern int have_illegal; + have_illegal = 1; + } +#endif + return 0; +} +#endif + + +#ifdef EMU_M68K +static int SekIntAckM68K(int level) +{ + if (level == 4) { Pico.video.pending_ints = 0; elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCycleCnt); } + else if(level == 6) { Pico.video.pending_ints &= ~0x20; elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCycleCnt); } + CPU_INT_LEVEL = 0; + return M68K_INT_ACK_AUTOVECTOR; +} + +static int SekTasCallback(void) +{ + return 0; // no writeback +} +#endif + + +#ifdef EMU_F68K +static void SekIntAckF68K(unsigned level) +{ + if (level == 4) { + Pico.video.pending_ints = 0; + elprintf(EL_INTS, "hack: @ %06x [%i]", SekPc, SekCyclesDone()); + } + else if(level == 6) { + Pico.video.pending_ints &= ~0x20; + elprintf(EL_INTS, "vack: @ %06x [%i]", SekPc, SekCyclesDone()); + } + PicoCpuFM68k.interrupts[0] = 0; +} +#endif + + +PICO_INTERNAL void SekInit(void) +{ +#ifdef EMU_C68K + CycloneInit(); + memset(&PicoCpuCM68k,0,sizeof(PicoCpuCM68k)); + PicoCpuCM68k.IrqCallback=SekIntAck; + PicoCpuCM68k.ResetCallback=SekResetAck; + PicoCpuCM68k.UnrecognizedCallback=SekUnrecognizedOpcode; + PicoCpuCM68k.flags=4; // Z set +#endif +#ifdef EMU_M68K + { + void *oldcontext = m68ki_cpu_p; + m68k_set_context(&PicoCpuMM68k); + m68k_set_cpu_type(M68K_CPU_TYPE_68000); + m68k_init(); + m68k_set_int_ack_callback(SekIntAckM68K); + m68k_set_tas_instr_callback(SekTasCallback); + //m68k_pulse_reset(); + m68k_set_context(oldcontext); + } +#endif +#ifdef EMU_F68K + { + void *oldcontext = g_m68kcontext; + g_m68kcontext = &PicoCpuFM68k; + memset(&PicoCpuFM68k, 0, sizeof(PicoCpuFM68k)); + fm68k_init(); + PicoCpuFM68k.iack_handler = SekIntAckF68K; + PicoCpuFM68k.sr = 0x2704; // Z flag + g_m68kcontext = oldcontext; + } +#endif +} + + +// Reset the 68000: +PICO_INTERNAL int SekReset(void) +{ + if (Pico.rom==NULL) return 1; + +#ifdef EMU_C68K + CycloneReset(&PicoCpuCM68k); +#endif +#ifdef EMU_M68K + m68k_set_context(&PicoCpuMM68k); // if we ever reset m68k, we always need it's context to be set + m68ki_cpu.sp[0]=0; + m68k_set_irq(0); + m68k_pulse_reset(); + REG_USP = 0; // ? +#endif +#ifdef EMU_F68K + { + g_m68kcontext = &PicoCpuFM68k; + fm68k_reset(); + } +#endif + + return 0; +} + +void SekStepM68k(void) +{ + SekCycleAim=SekCycleCnt+1; +#if defined(EMU_CORE_DEBUG) + SekCycleCnt+=CM_compareRun(1, 0); +#elif defined(EMU_C68K) + PicoCpuCM68k.cycles=1; + CycloneRun(&PicoCpuCM68k); + SekCycleCnt+=1-PicoCpuCM68k.cycles; +#elif defined(EMU_M68K) + SekCycleCnt+=m68k_execute(1); +#elif defined(EMU_F68K) + SekCycleCnt+=fm68k_emulate(1, 0); +#endif +} + +PICO_INTERNAL void SekSetRealTAS(int use_real) +{ +#ifdef EMU_C68K + CycloneSetRealTAS(use_real); +#endif +#ifdef EMU_F68K + // TODO +#endif +} + +// Pack the cpu into a common format: +// XXX: rename +PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub) +{ + unsigned int pc=0; + +#if defined(EMU_C68K) + struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k; + memcpy(cpu,context->d,0x40); + pc=context->pc-context->membase; + *(unsigned int *)(cpu+0x44)=CycloneGetSr(context); + *(unsigned int *)(cpu+0x48)=context->osp; + cpu[0x4c] = context->irq; + cpu[0x4d] = context->state_flags & 1; +#elif defined(EMU_M68K) + void *oldcontext = m68ki_cpu_p; + m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k); + memcpy(cpu,m68ki_cpu_p->dar,0x40); + pc=m68ki_cpu_p->pc; + *(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR); + *(unsigned int *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]; + cpu[0x4c] = CPU_INT_LEVEL>>8; + cpu[0x4d] = CPU_STOPPED; + m68k_set_context(oldcontext); +#elif defined(EMU_F68K) + M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; + memcpy(cpu,context->dreg,0x40); + pc=context->pc; + *(unsigned int *)(cpu+0x44)=context->sr; + *(unsigned int *)(cpu+0x48)=context->asp; + cpu[0x4c] = context->interrupts[0]; + cpu[0x4d] = (context->execinfo & FM68K_HALTED) ? 1 : 0; +#endif + + *(unsigned int *)(cpu+0x40) = pc; + *(unsigned int *)(cpu+0x50) = + is_sub ? SekCycleCntS68k : SekCycleCnt; +} + +PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub) +{ +#if defined(EMU_C68K) + struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k; + CycloneSetSr(context, *(unsigned int *)(cpu+0x44)); + context->osp=*(unsigned int *)(cpu+0x48); + memcpy(context->d,cpu,0x40); + context->membase = 0; + context->pc = *(unsigned int *)(cpu+0x40); + CycloneUnpack(context, NULL); // rebase PC + context->irq = cpu[0x4c]; + context->state_flags = 0; + if (cpu[0x4d]) + context->state_flags |= 1; +#elif defined(EMU_M68K) + void *oldcontext = m68ki_cpu_p; + m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k); + m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44)); + memcpy(m68ki_cpu_p->dar,cpu,0x40); + m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40); + m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(unsigned int *)(cpu+0x48); + CPU_INT_LEVEL = cpu[0x4c] << 8; + CPU_STOPPED = cpu[0x4d]; + m68k_set_context(oldcontext); +#elif defined(EMU_F68K) + M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k; + memcpy(context->dreg,cpu,0x40); + context->pc =*(unsigned int *)(cpu+0x40); + context->sr =*(unsigned int *)(cpu+0x44); + context->asp=*(unsigned int *)(cpu+0x48); + context->interrupts[0] = cpu[0x4c]; + context->execinfo &= ~FM68K_HALTED; + if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED; +#endif + if (is_sub) + SekCycleCntS68k = *(unsigned int *)(cpu+0x50); + else + SekCycleCnt = *(unsigned int *)(cpu+0x50); +} + + +/* idle loop detection, not to be used in CD mode */ +#ifdef EMU_C68K +#include "cpu/cyclone/tools/idle.h" +#endif + +static unsigned short **idledet_ptrs = NULL; +static int idledet_count = 0, idledet_bads = 0; +static int idledet_start_frame = 0; + +#if 0 +#define IDLE_STATS 1 +unsigned int idlehit_addrs[128], idlehit_counts[128]; + +void SekRegisterIdleHit(unsigned int pc) +{ + int i; + for (i = 0; i < 127 && idlehit_addrs[i]; i++) { + if (idlehit_addrs[i] == pc) { + idlehit_counts[i]++; + return; + } + } + idlehit_addrs[i] = pc; + idlehit_counts[i] = 1; + idlehit_addrs[i+1] = 0; +} +#endif + +void SekInitIdleDet(void) +{ + unsigned short **tmp = realloc(idledet_ptrs, 0x200*4); + if (tmp == NULL) { + free(idledet_ptrs); + idledet_ptrs = NULL; + } + else + idledet_ptrs = tmp; + idledet_count = idledet_bads = 0; + idledet_start_frame = Pico.m.frame_count + 360; +#ifdef IDLE_STATS + idlehit_addrs[0] = 0; +#endif + +#ifdef EMU_C68K + CycloneInitIdle(); +#endif +#ifdef EMU_F68K + fm68k_emulate(0, 1); +#endif +} + +int SekIsIdleReady(void) +{ + return (Pico.m.frame_count >= idledet_start_frame); +} + +int SekIsIdleCode(unsigned short *dst, int bytes) +{ + // printf("SekIsIdleCode %04x %i\n", *dst, bytes); + switch (bytes) + { + case 2: + if ((*dst & 0xf000) != 0x6000) // not another branch + return 1; + break; + case 4: + if ( (*dst & 0xff3f) == 0x4a38 || // tst.x ($xxxx.w); tas ($xxxx.w) + (*dst & 0xc1ff) == 0x0038 || // move.x ($xxxx.w), dX + (*dst & 0xf13f) == 0xb038) // cmp.x ($xxxx.w), dX + return 1; + if (PicoAHW & (PAHW_MCD|PAHW_32X)) + break; + // with no addons, there should be no need to wait + // for byte change anywhere + if ( (*dst & 0xfff8) == 0x4a10 || // tst.b ($aX) + (*dst & 0xfff8) == 0x4a28) // tst.b ($xxxx,a0) + return 1; + break; + case 6: + if ( ((dst[1] & 0xe0) == 0xe0 && ( // RAM and + *dst == 0x4a39 || // tst.b ($xxxxxxxx) + *dst == 0x4a79 || // tst.w ($xxxxxxxx) + *dst == 0x4ab9 || // tst.l ($xxxxxxxx) + (*dst & 0xc1ff) == 0x0039 || // move.x ($xxxxxxxx), dX + (*dst & 0xf13f) == 0xb039))||// cmp.x ($xxxxxxxx), dX + *dst == 0x0838 || // btst $X, ($xxxx.w) [6 byte op] + (*dst & 0xffbf) == 0x0c38) // cmpi.{b,w} $X, ($xxxx.w) + return 1; + break; + case 8: + if ( ((dst[2] & 0xe0) == 0xe0 && ( // RAM and + *dst == 0x0839 || // btst $X, ($xxxxxxxx.w) [8 byte op] + (*dst & 0xffbf) == 0x0c39))||// cmpi.{b,w} $X, ($xxxxxxxx) + *dst == 0x0cb8) // cmpi.l $X, ($xxxx.w) + return 1; + break; + case 12: + if (PicoAHW & (PAHW_MCD|PAHW_32X)) + break; + if ( (*dst & 0xf1f8) == 0x3010 && // move.w (aX), dX + (dst[1]&0xf100) == 0x0000 && // arithmetic + (dst[3]&0xf100) == 0x0000) // arithmetic + return 1; + break; + } + + return 0; +} + +int SekRegisterIdlePatch(unsigned int pc, int oldop, int newop, void *ctx) +{ + int is_main68k = 1; + u16 *target; + uptr v; + +#if defined(EMU_C68K) + struct Cyclone *cyc = ctx; + is_main68k = cyc == &PicoCpuCM68k; + pc -= cyc->membase; +#elif defined(EMU_F68K) + is_main68k = ctx == &PicoCpuFM68k; +#endif + pc &= ~0xff000000; + if (!(newop&0x200)) + elprintf(EL_IDLE, "idle: patch %06x %04x %04x %c %c #%i", pc, oldop, newop, + (newop&0x200)?'n':'y', is_main68k?'m':'s', idledet_count); + + // XXX: probably shouldn't patch RAM too + v = m68k_read16_map[pc >> M68K_MEM_SHIFT]; + if (!(v & 0x80000000)) + target = (u16 *)((v << 1) + pc); + else { + if (++idledet_bads > 128) + return 2; // remove detector + return 1; // don't patch + } + + if (idledet_count >= 0x200 && (idledet_count & 0x1ff) == 0) { + unsigned short **tmp = realloc(idledet_ptrs, (idledet_count+0x200)*4); + if (tmp == NULL) + return 1; + idledet_ptrs = tmp; + } + + idledet_ptrs[idledet_count++] = target; + + return 0; +} + +void SekFinishIdleDet(void) +{ +#ifdef EMU_C68K + CycloneFinishIdle(); +#endif +#ifdef EMU_F68K + fm68k_emulate(0, 2); +#endif + while (idledet_count > 0) + { + unsigned short *op = idledet_ptrs[--idledet_count]; + if ((*op & 0xfd00) == 0x7100) + *op &= 0xff, *op |= 0x6600; + else if ((*op & 0xfd00) == 0x7500) + *op &= 0xff, *op |= 0x6700; + else if ((*op & 0xfd00) == 0x7d00) + *op &= 0xff, *op |= 0x6000; + else + elprintf(EL_STATUS|EL_IDLE, "idle: don't know how to restore %04x", *op); + } +} + + +#if defined(CPU_CMP_R) || defined(CPU_CMP_W) +#include "debug.h" + +struct ref_68k { + u32 dar[16]; + u32 pc; + u32 sr; + u32 cycles; + u32 pc_prev; +}; +struct ref_68k ref_68ks[2]; +static int current_68k; + +void SekTrace(int is_s68k) +{ + struct ref_68k *x68k = &ref_68ks[is_s68k]; + u32 pc = is_s68k ? SekPcS68k : SekPc; + u32 sr = is_s68k ? SekSrS68k : SekSr; + u32 cycles = is_s68k ? SekCycleCntS68k : SekCycleCnt; + u32 r; + u8 cmd; +#ifdef CPU_CMP_W + int i; + + if (is_s68k != current_68k) { + current_68k = is_s68k; + cmd = CTL_68K_SLAVE | current_68k; + tl_write(&cmd, sizeof(cmd)); + } + if (pc != x68k->pc) { + x68k->pc = pc; + tl_write_uint(CTL_68K_PC, x68k->pc); + } + if (sr != x68k->sr) { + x68k->sr = sr; + tl_write_uint(CTL_68K_SR, x68k->sr); + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + x68k->dar[i] = r; + tl_write_uint(CTL_68K_R + i, r); + } + } + tl_write_uint(CTL_68K_CYCLES, cycles); +#else + int i, bad = 0; + + while (1) + { + int ret = tl_read(&cmd, sizeof(cmd)); + if (ret == 0) { + elprintf(EL_STATUS, "EOF"); + exit(1); + } + switch (cmd) { + case CTL_68K_SLAVE: + case CTL_68K_SLAVE + 1: + current_68k = cmd & 1; + break; + case CTL_68K_PC: + tl_read_uint(&x68k->pc); + break; + case CTL_68K_SR: + tl_read_uint(&x68k->sr); + break; + case CTL_68K_CYCLES: + tl_read_uint(&x68k->cycles); + goto breakloop; + default: + if (CTL_68K_R <= cmd && cmd < CTL_68K_R + 0x10) + tl_read_uint(&x68k->dar[cmd - CTL_68K_R]); + else + elprintf(EL_STATUS, "invalid cmd: %02x", cmd); + } + } + +breakloop: + if (is_s68k != current_68k) { + printf("bad 68k: %d %d\n", is_s68k, current_68k); + bad = 1; + } + if (cycles != x68k->cycles) { + printf("bad cycles: %u %u\n", cycles, x68k->cycles); + bad = 1; + } + if ((pc ^ x68k->pc) & 0xffffff) { + printf("bad PC: %08x %08x\n", pc, x68k->pc); + bad = 1; + } + if (sr != x68k->sr) { + printf("bad SR: %03x %03x\n", sr, x68k->sr); + bad = 1; + } + for (i = 0; i < 16; i++) { + r = is_s68k ? SekDarS68k(i) : SekDar(i); + if (r != x68k->dar[i]) { + printf("bad %c%d: %08x %08x\n", i < 8 ? 'D' : 'A', i & 7, + r, x68k->dar[i]); + bad = 1; + } + } + if (bad) { + for (i = 0; i < 8; i++) + printf("D%d: %08x A%d: %08x\n", i, x68k->dar[i], + i, x68k->dar[i + 8]); + printf("PC: %08x, %08x\n", x68k->pc, x68k->pc_prev); + + PDebugDumpMem(); + exit(1); + } + x68k->pc_prev = x68k->pc; +#endif +} +#endif // CPU_CMP_* + +#if defined(EMU_M68K) && M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER +static unsigned char op_flags[0x400000/2] = { 0, }; +static int atexit_set = 0; + +static void make_idc(void) +{ + FILE *f = fopen("idc.idc", "w"); + int i; + if (!f) return; + fprintf(f, "#include \nstatic main() {\n"); + for (i = 0; i < 0x400000/2; i++) + if (op_flags[i] != 0) + fprintf(f, " MakeCode(0x%06x);\n", i*2); + fprintf(f, "}\n"); + fclose(f); +} + +void instruction_hook(void) +{ + if (!atexit_set) { + atexit(make_idc); + atexit_set = 1; + } + if (REG_PC < 0x400000) + op_flags[REG_PC/2] = 1; +} +#endif + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/sms.c b/waterbox/picodrive/pico/sms.c new file mode 100644 index 0000000000..8c44d51ffc --- /dev/null +++ b/waterbox/picodrive/pico/sms.c @@ -0,0 +1,316 @@ +/* + * SMS emulation + * (C) notaz, 2009-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ +/* + * TODO: + * - start in a state as if BIOS ran + * - remaining status flags (OVR/COL) + * - RAM support in mapper + * - region support + * - SN76496 DAC-like usage + * - H counter + */ +#include "pico_int.h" +#include "memory.h" +#include "sound/sn76496.h" + +static unsigned char vdp_data_read(void) +{ + struct PicoVideo *pv = &Pico.video; + unsigned char d; + + d = Pico.vramb[pv->addr]; + pv->addr = (pv->addr + 1) & 0x3fff; + pv->pending = 0; + return d; +} + +static unsigned char vdp_ctl_read(void) +{ + unsigned char d = Pico.video.pending_ints << 7; + Pico.video.pending = 0; + Pico.video.pending_ints = 0; + + elprintf(EL_SR, "VDP sr: %02x", d); + return d; +} + +static void vdp_data_write(unsigned char d) +{ + struct PicoVideo *pv = &Pico.video; + + if (pv->type == 3) { + Pico.cram[pv->addr & 0x1f] = d; + Pico.m.dirtyPal = 1; + } else { + Pico.vramb[pv->addr] = d; + } + pv->addr = (pv->addr + 1) & 0x3fff; + + pv->pending = 0; +} + +static void vdp_ctl_write(unsigned char d) +{ + struct PicoVideo *pv = &Pico.video; + + if (pv->pending) { + if ((d >> 6) == 2) { + pv->reg[d & 0x0f] = pv->addr; + elprintf(EL_IO, " VDP r%02x=%02x", d & 0x0f, pv->addr & 0xff); + } + pv->type = d >> 6; + pv->addr &= 0x00ff; + pv->addr |= (d & 0x3f) << 8; + } else { + pv->addr &= 0x3f00; + pv->addr |= d; + } + pv->pending ^= 1; +} + +static unsigned char z80_sms_in(unsigned short a) +{ + unsigned char d = 0; + + elprintf(EL_IO, "z80 port %04x read", a); + a &= 0xc1; + switch (a) + { + case 0x00: + case 0x01: + d = 0xff; + break; + + case 0x40: /* V counter */ + d = Pico.video.v_counter; + elprintf(EL_HVCNT, "V counter read: %02x", d); + break; + + case 0x41: /* H counter */ + d = Pico.m.rotate++; + elprintf(EL_HVCNT, "H counter read: %02x", d); + break; + + case 0x80: + d = vdp_data_read(); + break; + + case 0x81: + d = vdp_ctl_read(); + break; + + case 0xc0: /* I/O port A and B */ + d = ~((PicoPad[0] & 0x3f) | (PicoPad[1] << 6)); + break; + + case 0xc1: /* I/O port B and miscellaneous */ + d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30; + d |= ~(PicoPad[1] >> 2) & 0x0f; + break; + } + + elprintf(EL_IO, "ret = %02x", d); + return d; +} + +static void z80_sms_out(unsigned short a, unsigned char d) +{ + elprintf(EL_IO, "z80 port %04x write %02x", a, d); + a &= 0xc1; + switch (a) + { + case 0x01: + Pico.ms.io_ctl = d; + break; + + case 0x40: + case 0x41: + if (PicoOpt & POPT_EN_PSG) + SN76496Write(d); + break; + + case 0x80: + vdp_data_write(d); + break; + + case 0x81: + vdp_ctl_write(d); + break; + } +} + +static int bank_mask; + +static void write_bank(unsigned short a, unsigned char d) +{ + elprintf(EL_Z80BNK, "bank %04x %02x @ %04x", a, d, z80_pc()); + switch (a & 0x0f) + { + case 0x0c: + elprintf(EL_STATUS|EL_ANOMALY, "%02x written to control reg!", d); + break; + case 0x0d: + if (d != 0) + elprintf(EL_STATUS|EL_ANOMALY, "bank0 changed to %d!", d); + break; + case 0x0e: + d &= bank_mask; + z80_map_set(z80_read_map, 0x4000, 0x7fff, Pico.rom + (d << 14), 0); +#ifdef _USE_CZ80 + Cz80_Set_Fetch(&CZ80, 0x4000, 0x7fff, (FPTR)Pico.rom + (d << 14)); +#endif + break; + case 0x0f: + d &= bank_mask; + z80_map_set(z80_read_map, 0x8000, 0xbfff, Pico.rom + (d << 14), 0); +#ifdef _USE_CZ80 + Cz80_Set_Fetch(&CZ80, 0x8000, 0xbfff, (FPTR)Pico.rom + (d << 14)); +#endif + break; + } + Pico.ms.carthw[a & 0x0f] = d; +} + +static void xwrite(unsigned int a, unsigned char d) +{ + elprintf(EL_IO, "z80 write [%04x] %02x", a, d); + if (a >= 0xc000) + Pico.zram[a & 0x1fff] = d; + if (a >= 0xfff8) + write_bank(a, d); +} + +void PicoResetMS(void) +{ + z80_reset(); + PsndReset(); // pal must be known here +} + +void PicoPowerMS(void) +{ + int s, tmp; + + memset(&Pico.ram,0,(unsigned char *)&Pico.rom - Pico.ram); + memset(&Pico.video,0,sizeof(Pico.video)); + memset(&Pico.m,0,sizeof(Pico.m)); + Pico.m.pal = 0; + + // calculate a mask for bank writes. + // ROM loader has aligned the size for us, so this is safe. + s = 0; tmp = Pico.romsize; + while ((tmp >>= 1) != 0) + s++; + if (Pico.romsize > (1 << s)) + s++; + tmp = 1 << s; + bank_mask = (tmp - 1) >> 14; + + Pico.ms.carthw[0x0e] = 1; + Pico.ms.carthw[0x0f] = 2; + + PicoReset(); +} + +void PicoMemSetupMS(void) +{ + z80_map_set(z80_read_map, 0x0000, 0xbfff, Pico.rom, 0); + z80_map_set(z80_read_map, 0xc000, 0xdfff, Pico.zram, 0); + z80_map_set(z80_read_map, 0xe000, 0xffff, Pico.zram, 0); + + z80_map_set(z80_write_map, 0x0000, 0xbfff, xwrite, 1); + z80_map_set(z80_write_map, 0xc000, 0xdfff, Pico.zram, 0); + z80_map_set(z80_write_map, 0xe000, 0xffff, xwrite, 1); + +#ifdef _USE_DRZ80 + drZ80.z80_in = z80_sms_in; + drZ80.z80_out = z80_sms_out; +#endif +#ifdef _USE_CZ80 + Cz80_Set_Fetch(&CZ80, 0x0000, 0xbfff, (FPTR)Pico.rom); + Cz80_Set_Fetch(&CZ80, 0xc000, 0xdfff, (FPTR)Pico.zram); + Cz80_Set_Fetch(&CZ80, 0xe000, 0xffff, (FPTR)Pico.zram); + Cz80_Set_INPort(&CZ80, z80_sms_in); + Cz80_Set_OUTPort(&CZ80, z80_sms_out); +#endif +} + +void PicoStateLoadedMS(void) +{ + write_bank(0xfffe, Pico.ms.carthw[0x0e]); + write_bank(0xffff, Pico.ms.carthw[0x0f]); +} + +void PicoFrameMS(void) +{ + struct PicoVideo *pv = &Pico.video; + int is_pal = Pico.m.pal; + int lines = is_pal ? 313 : 262; + int cycles_line = is_pal ? 58020 : 58293; /* (226.6 : 227.7) * 256 */ + int cycles_done = 0, cycles_aim = 0; + int skip = PicoSkipFrame; + int lines_vis = 192; + int hint; // Hint counter + int nmi; + int y; + + nmi = (PicoPad[0] >> 7) & 1; + if (!Pico.ms.nmi_state && nmi) + z80_nmi(); + Pico.ms.nmi_state = nmi; + + PicoFrameStartMode4(); + hint = pv->reg[0x0a]; + + for (y = 0; y < lines; y++) + { + pv->v_counter = Pico.m.scanline = y; + if (y > 218) + pv->v_counter = y - 6; + + if (y < lines_vis && !skip) + PicoLineMode4(y); + + if (y <= lines_vis) + { + if (--hint < 0) + { + hint = pv->reg[0x0a]; + pv->pending_ints |= 2; + if (pv->reg[0] & 0x10) { + elprintf(EL_INTS, "hint"); + z80_int(); + } + } + } + else if (y == lines_vis + 1) { + pv->pending_ints |= 1; + if (pv->reg[1] & 0x20) { + elprintf(EL_INTS, "vint"); + z80_int(); + } + } + + cycles_aim += cycles_line; + cycles_done += z80_run((cycles_aim - cycles_done) >> 8) << 8; + } + + if (PsndOut) + PsndGetSamplesMS(); +} + +void PicoFrameDrawOnlyMS(void) +{ + int lines_vis = 192; + int y; + + PicoFrameStartMode4(); + + for (y = 0; y < lines_vis; y++) + PicoLineMode4(y); +} + diff --git a/waterbox/picodrive/pico/sound/mix.c b/waterbox/picodrive/pico/sound/mix.c new file mode 100644 index 0000000000..636edb553b --- /dev/null +++ b/waterbox/picodrive/pico/sound/mix.c @@ -0,0 +1,79 @@ +/* + * some code for sample mixing + * (C) notaz, 2006,2007 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#define MAXOUT (+32767) +#define MINOUT (-32768) + +/* limitter */ +#define Limit(val, max,min) { \ + if ( val > max ) val = max; \ + else if ( val < min ) val = min; \ +} + + +void mix_32_to_16l_stereo(short *dest, int *src, int count) +{ + int l, r; + + for (; count > 0; count--) + { + l = r = *dest; + l += *src++; + r += *src++; + Limit( l, MAXOUT, MINOUT ); + Limit( r, MAXOUT, MINOUT ); + *dest++ = l; + *dest++ = r; + } +} + + +void mix_32_to_16_mono(short *dest, int *src, int count) +{ + int l; + + for (; count > 0; count--) + { + l = *dest; + l += *src++; + Limit( l, MAXOUT, MINOUT ); + *dest++ = l; + } +} + + +void mix_16h_to_32(int *dest_buf, short *mp3_buf, int count) +{ + while (count--) + { + *dest_buf++ += *mp3_buf++ >> 1; + } +} + +void mix_16h_to_32_s1(int *dest_buf, short *mp3_buf, int count) +{ + count >>= 1; + while (count--) + { + *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += *mp3_buf++ >> 1; + mp3_buf += 1*2; + } +} + +void mix_16h_to_32_s2(int *dest_buf, short *mp3_buf, int count) +{ + count >>= 1; + while (count--) + { + *dest_buf++ += *mp3_buf++ >> 1; + *dest_buf++ += *mp3_buf++ >> 1; + mp3_buf += 3*2; + } +} + diff --git a/waterbox/picodrive/pico/sound/mix.h b/waterbox/picodrive/pico/sound/mix.h new file mode 100644 index 0000000000..b9315114c9 --- /dev/null +++ b/waterbox/picodrive/pico/sound/mix.h @@ -0,0 +1,10 @@ + +//void mix_32_to_32(int *dest, int *src, int count); +void mix_16h_to_32(int *dest, short *src, int count); +void mix_16h_to_32_s1(int *dest, short *src, int count); +void mix_16h_to_32_s2(int *dest, short *src, int count); +void mix_32_to_16l_stereo(short *dest, int *src, int count); +void mix_32_to_16_mono(short *dest, int *src, int count); + +extern int mix_32_to_16l_level; +void mix_32_to_16l_stereo_lvl(short *dest, int *src, int count); diff --git a/waterbox/picodrive/pico/sound/sn76496.c b/waterbox/picodrive/pico/sound/sn76496.c new file mode 100644 index 0000000000..8474c70369 --- /dev/null +++ b/waterbox/picodrive/pico/sound/sn76496.c @@ -0,0 +1,344 @@ +/*************************************************************************** + + sn76496.c + + Routines to emulate the Texas Instruments SN76489 / SN76496 programmable + tone /noise generator. Also known as (or at least compatible with) TMS9919. + + Noise emulation is not accurate due to lack of documentation. The noise + generator uses a shift register with a XOR-feedback network, but the exact + layout is unknown. It can be set for either period or white noise; again, + the details are unknown. + + 28/03/2005 : Sebastien Chevalier + Update th SN76496Write func, according to SN76489 doc found on SMSPower. + - On write with 0x80 set to 0, when LastRegister is other then TONE, + the function is similar than update with 0x80 set to 1 +***************************************************************************/ + +#ifndef __GNUC__ +#pragma warning (disable:4244) +#endif + +#include "sn76496.h" + +#define MAX_OUTPUT 0x47ff // was 0x7fff + +#define STEP 0x10000 + + +/* Formulas for noise generator */ +/* bit0 = output */ + +/* noise feedback for white noise mode (verified on real SN76489 by John Kortink) */ +#define FB_WNOISE 0x14002 /* (16bits) bit16 = bit0(out) ^ bit2 ^ bit15 */ + +/* noise feedback for periodic noise mode */ +//#define FB_PNOISE 0x10000 /* 16bit rorate */ +#define FB_PNOISE 0x08000 /* JH 981127 - fixes Do Run Run */ + +/* +0x08000 is definitely wrong. The Master System conversion of Marble Madness +uses periodic noise as a baseline. With a 15-bit rotate, the bassline is +out of tune. +The 16-bit rotate has been confirmed against a real PAL Sega Master System 2. +Hope that helps the System E stuff, more news on the PSG as and when! +*/ + +/* noise generator start preset (for periodic noise) */ +#define NG_PRESET 0x0f35 + + +struct SN76496 +{ + //sound_stream * Channel; + int SampleRate; + unsigned int UpdateStep; + int VolTable[16]; /* volume table */ + int Register[8]; /* registers */ + int LastRegister; /* last register written */ + int Volume[4]; /* volume of voice 0-2 and noise */ + unsigned int RNG; /* noise generator */ + int NoiseFB; /* noise feedback mask */ + int Period[4]; + int Count[4]; + int Output[4]; + int pad[1]; +}; + +static struct SN76496 ono_sn; // one and only SN76496 +int *sn76496_regs; + +//static +void SN76496Write(int data) +{ + struct SN76496 *R = &ono_sn; + int n; + + + /* update the output buffer before changing the registers */ + //stream_update(R->Channel,0); + + if (data & 0x80) + { + int r = (data & 0x70) >> 4; + int c = r/2; + + R->LastRegister = r; + R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); + switch (r) + { + case 0: /* tone 0 : frequency */ + 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 == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + case 1: /* tone 0 : volume */ + case 3: /* tone 1 : volume */ + case 5: /* tone 2 : volume */ + case 7: /* noise : volume */ + R->Volume[c] = R->VolTable[data & 0x0f]; + break; + case 6: /* noise : frequency, mode */ + { + int n = R->Register[6]; + R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; + n &= 3; + /* N/512,N/1024,N/2048,Tone #3 output */ + R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+(n&3))); + + /* reset noise shifter */ + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + } + break; + } + } + else + { + int r = R->LastRegister; + int c = r/2; + + switch (r) + { + case 0: /* tone 0 : frequency */ + case 2: /* tone 1 : frequency */ + 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 == 4) + { + /* update noise shift frequency */ + if ((R->Register[6] & 0x03) == 0x03) + R->Period[3] = 2 * R->Period[2]; + } + break; + case 1: /* tone 0 : volume */ + case 3: /* tone 1 : volume */ + case 5: /* tone 2 : volume */ + case 7: /* noise : volume */ + R->Volume[c] = R->VolTable[data & 0x0f]; + R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); + break; + case 6: /* noise : frequency, mode */ + { + R->Register[r] = (R->Register[r] & 0x3f0) | (data & 0x0f); + n = R->Register[6]; + R->NoiseFB = (n & 4) ? FB_WNOISE : FB_PNOISE; + n &= 3; + /* N/512,N/1024,N/2048,Tone #3 output */ + R->Period[3] = ((n&3) == 3) ? 2 * R->Period[2] : (R->UpdateStep << (5+(n&3))); + + /* reset noise shifter */ + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + } + break; + } + } +} + +/* +WRITE8_HANDLER( SN76496_0_w ) { SN76496Write(0,data); } +WRITE8_HANDLER( SN76496_1_w ) { SN76496Write(1,data); } +WRITE8_HANDLER( SN76496_2_w ) { SN76496Write(2,data); } +WRITE8_HANDLER( SN76496_3_w ) { SN76496Write(3,data); } +WRITE8_HANDLER( SN76496_4_w ) { SN76496Write(4,data); } +*/ + +//static +void SN76496Update(short *buffer, int length, int stereo) +{ + int i; + struct SN76496 *R = &ono_sn; + + /* If the volume is 0, increase the counter */ + for (i = 0;i < 4;i++) + { + if (R->Volume[i] == 0) + { + /* note that I do count += length, NOT count = length + 1. You might think */ + /* it's the same since the volume is 0, but doing the latter could cause */ + /* interferencies when the program is rapidly modulating the volume. */ + if (R->Count[i] <= length*STEP) R->Count[i] += length*STEP; + } + } + + while (length > 0) + { + int vol[4]; + unsigned int out; + int left; + + + /* vol[] keeps track of how long each square wave stays */ + /* in the 1 position during the sample period. */ + vol[0] = vol[1] = vol[2] = vol[3] = 0; + + for (i = 0;i < 3;i++) + { + if (R->Output[i]) vol[i] += R->Count[i]; + R->Count[i] -= STEP; + /* Period[i] is the half period of the square wave. Here, in each */ + /* loop I add Period[i] twice, so that at the end of the loop the */ + /* square wave is in the same status (0 or 1) it was at the start. */ + /* vol[i] is also incremented by Period[i], since the wave has been 1 */ + /* exactly half of the time, regardless of the initial position. */ + /* If we exit the loop in the middle, Output[i] has to be inverted */ + /* and vol[i] incremented only if the exit status of the square */ + /* wave is 1. */ + while (R->Count[i] <= 0) + { + R->Count[i] += R->Period[i]; + if (R->Count[i] > 0) + { + R->Output[i] ^= 1; + if (R->Output[i]) vol[i] += R->Period[i]; + break; + } + R->Count[i] += R->Period[i]; + vol[i] += R->Period[i]; + } + if (R->Output[i]) vol[i] -= R->Count[i]; + } + + left = STEP; + do + { + int nextevent; + + if (R->Count[3] < left) nextevent = R->Count[3]; + else nextevent = left; + + if (R->Output[3]) vol[3] += R->Count[3]; + R->Count[3] -= nextevent; + if (R->Count[3] <= 0) + { + if (R->RNG & 1) R->RNG ^= R->NoiseFB; + R->RNG >>= 1; + R->Output[3] = R->RNG & 1; + R->Count[3] += R->Period[3]; + if (R->Output[3]) vol[3] += R->Period[3]; + } + if (R->Output[3]) vol[3] -= R->Count[3]; + + left -= nextevent; + } while (left > 0); + + out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + + vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; + + if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; + + if ((out /= STEP)) // will be optimized to shift; max 0x47ff = 18431 + *buffer += out; + if(stereo) buffer+=2; // only left for stereo, to be mixed to right later + else buffer++; + + length--; + } +} + + +static void SN76496_set_clock(struct SN76496 *R,int clock) +{ + + /* the base clock for the tone generators is the chip clock divided by 16; */ + /* for the noise generator, it is clock / 256. */ + /* Here we calculate the number of steps which happen during one sample */ + /* at the given sample rate. No. of events = sample rate / (clock/16). */ + /* STEP is a multiplier used to turn the fraction into a fixed point */ + /* number. */ + R->UpdateStep = ((double)STEP * R->SampleRate * 16) / clock; +} + + +static void SN76496_set_gain(struct SN76496 *R,int gain) +{ + int i; + double out; + + + gain &= 0xff; + + /* increase max output basing on gain (0.2 dB per step) */ + out = MAX_OUTPUT / 3; + while (gain-- > 0) + out *= 1.023292992; /* = (10 ^ (0.2/20)) */ + + /* build volume table (2dB per step) */ + for (i = 0;i < 15;i++) + { + /* limit volume to avoid clipping */ + if (out > MAX_OUTPUT / 3) R->VolTable[i] = MAX_OUTPUT / 3; + else R->VolTable[i] = out; + + out /= 1.258925412; /* = 10 ^ (2/20) = 2dB */ + } + R->VolTable[15] = 0; +} + + +//static +int SN76496_init(int clock,int sample_rate) +{ + struct SN76496 *R = &ono_sn; + int i; + + //R->Channel = stream_create(0,1, sample_rate,R,SN76496Update); + sn76496_regs = R->Register; + + R->SampleRate = sample_rate; + SN76496_set_clock(R,clock); + + for (i = 0;i < 4;i++) R->Volume[i] = 0; + + R->LastRegister = 0; + for (i = 0;i < 8;i+=2) + { + R->Register[i] = 0; + R->Register[i + 1] = 0x0f; /* volume = 0 */ + } + + for (i = 0;i < 4;i++) + { + R->Output[i] = 0; + R->Period[i] = R->Count[i] = R->UpdateStep; + } + R->RNG = NG_PRESET; + R->Output[3] = R->RNG & 1; + + // added + SN76496_set_gain(R, 0); + + return 0; +} + diff --git a/waterbox/picodrive/pico/sound/sn76496.h b/waterbox/picodrive/pico/sound/sn76496.h new file mode 100644 index 0000000000..e0de6edaf5 --- /dev/null +++ b/waterbox/picodrive/pico/sound/sn76496.h @@ -0,0 +1,8 @@ +#ifndef SN76496_H +#define SN76496_H + +void SN76496Write(int data); +void SN76496Update(short *buffer,int length,int stereo); +int SN76496_init(int clock,int sample_rate); + +#endif diff --git a/waterbox/picodrive/pico/sound/sound.c b/waterbox/picodrive/pico/sound/sound.c new file mode 100644 index 0000000000..69c1be0397 --- /dev/null +++ b/waterbox/picodrive/pico/sound/sound.c @@ -0,0 +1,384 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2009 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include +#include "ym2612.h" +#include "sn76496.h" +#include "../pico_int.h" +#include "../cd/cue.h" +#include "mix.h" + +#define SIMPLE_WRITE_SOUND 0 + +void (*PsndMix_32_to_16l)(short *dest, int *src, int count) = mix_32_to_16l_stereo; + +// master int buffer to mix to +static int PsndBuffer[2*(44100+100)/50]; + +// dac +static unsigned short dac_info[312+4]; // pppppppp ppppllll, p - pos in buff, l - length to write for this sample + +// cdda output buffer +short cdda_out_buffer[2*1152]; + +// for Pico +int PsndRate=0; +int PsndLen=0; // number of mono samples, multiply by 2 for stereo +int PsndLen_exc_add=0; // this is for non-integer sample counts per line, eg. 22050/60 +int PsndLen_exc_cnt=0; +int PsndDacLine=0; +short *PsndOut=NULL; // PCM data buffer + +// timers +int timer_a_next_oflow, timer_a_step; // in z80 cycles +int timer_b_next_oflow, timer_b_step; + +// sn76496 +extern int *sn76496_regs; + + +static void dac_recalculate(void) +{ + int i, dac_cnt, pos, len, lines = Pico.m.pal ? 312 : 262, mid = Pico.m.pal ? 68 : 93; + + if (PsndLen <= lines) + { + // shrinking algo + dac_cnt = -PsndLen; + len=1; pos=0; + dac_info[225] = 1; + + for(i=226; i != 225; i++) + { + if (i >= lines) i = 0; + len = 0; + if(dac_cnt < 0) { + len=1; + pos++; + dac_cnt += lines; + } + dac_cnt -= PsndLen; + dac_info[i] = (pos<<4)|len; + } + } + else + { + // stretching + dac_cnt = PsndLen; + pos=0; + for(i = 225; i != 224; i++) + { + if (i >= lines) i = 0; + len=0; + while(dac_cnt >= 0) { + dac_cnt -= lines; + len++; + } + if (i == mid) // midpoint + while(pos+len < PsndLen/2) { + dac_cnt -= lines; + len++; + } + dac_cnt += PsndLen; + dac_info[i] = (pos<<4)|len; + pos+=len; + } + // last sample + for(len = 0, i = pos; i < PsndLen; i++) len++; + if (PsndLen_exc_add) len++; + dac_info[224] = (pos<<4)|len; + } + mid = (dac_info[lines-1] & 0xfff0) + ((dac_info[lines-1] & 0xf) << 4); + for (i = lines; i < sizeof(dac_info) / sizeof(dac_info[0]); i++) + dac_info[i] = mid; + //for(i=len=0; i < lines; i++) { + // printf("%03i : %03i : %i\n", i, dac_info[i]>>4, dac_info[i]&0xf); + // len+=dac_info[i]&0xf; + //} + //printf("rate is %i, len %f\n", PsndRate, (double)PsndRate/(Pico.m.pal ? 50.0 : 60.0)); + //printf("len total: %i, last pos: %i\n", len, pos); + //exit(8); +} + + +PICO_INTERNAL void PsndReset(void) +{ + // PsndRerate calls YM2612Init, which also resets + PsndRerate(0); + timers_reset(); +} + + +// to be called after changing sound rate or chips +void PsndRerate(int preserve_state) +{ + void *state = NULL; + int target_fps = Pico.m.pal ? 50 : 60; + + if (preserve_state) { + state = malloc(0x204); + if (state == NULL) return; + ym2612_pack_state(); + memcpy(state, YM2612GetRegs(), 0x204); + } + YM2612Init(Pico.m.pal ? OSC_PAL/7 : OSC_NTSC/7, PsndRate); + if (preserve_state) { + // feed it back it's own registers, just like after loading state + memcpy(YM2612GetRegs(), state, 0x204); + ym2612_unpack_state(); + } + + if (preserve_state) memcpy(state, sn76496_regs, 28*4); // remember old state + SN76496_init(Pico.m.pal ? OSC_PAL/15 : OSC_NTSC/15, PsndRate); + if (preserve_state) memcpy(sn76496_regs, state, 28*4); // restore old state + + if (state) + free(state); + + // calculate PsndLen + PsndLen=PsndRate / target_fps; + PsndLen_exc_add=((PsndRate - PsndLen*target_fps)<<16) / target_fps; + PsndLen_exc_cnt=0; + + // recalculate dac info + dac_recalculate(); + + // clear all buffers + memset32(PsndBuffer, 0, sizeof(PsndBuffer)/4); + memset(cdda_out_buffer, 0, sizeof(cdda_out_buffer)); + if (PsndOut) + PsndClear(); + + // set mixer + PsndMix_32_to_16l = (PicoOpt & POPT_EN_STEREO) ? mix_32_to_16l_stereo : mix_32_to_16_mono; + + if (PicoAHW & PAHW_PICO) + PicoReratePico(); +} + + +PICO_INTERNAL void PsndDoDAC(int line_to) +{ + int pos, pos1, len; + int dout = ym2612.dacout; + int line_from = PsndDacLine; + + if (line_to >= 312) + line_to = 311; + + PsndDacLine = line_to + 1; + + pos =dac_info[line_from]>>4; + pos1=dac_info[line_to]; + len = ((pos1>>4)-pos) + (pos1&0xf); + if (!len) return; + + if (PicoOpt & POPT_EN_STEREO) { + short *d = PsndOut + pos*2; + for (; len > 0; len--, d+=2) *d = dout; + } else { + short *d = PsndOut + pos; + for (; len > 0; len--, d++) *d = dout; + } +} + +// cdda +static void cdda_raw_update(int *buffer, int length) +{ + int ret, cdda_bytes, mult = 1; + + cdda_bytes = length*4; + if (PsndRate <= 22050 + 100) mult = 2; + if (PsndRate < 22050 - 100) mult = 4; + cdda_bytes *= mult; + + ret = pm_read(cdda_out_buffer, cdda_bytes, Pico_mcd->cdda_stream); + if (ret < cdda_bytes) { + memset((char *)cdda_out_buffer + ret, 0, cdda_bytes - ret); + Pico_mcd->cdda_stream = NULL; + return; + } + + // now mix + switch (mult) { + case 1: mix_16h_to_32(buffer, cdda_out_buffer, length*2); break; + case 2: mix_16h_to_32_s1(buffer, cdda_out_buffer, length*2); break; + case 4: mix_16h_to_32_s2(buffer, cdda_out_buffer, length*2); break; + } +} + +void cdda_start_play(int lba_base, int lba_offset, int lb_len) +{ + if (Pico_mcd->cdda_type == CT_MP3) + { + int pos1024 = 0; + + if (lba_offset) + pos1024 = lba_offset * 1024 / lb_len; + + mp3_start_play(Pico_mcd->cdda_stream, pos1024); + return; + } + + pm_seek(Pico_mcd->cdda_stream, (lba_base + lba_offset) * 2352, SEEK_SET); + if (Pico_mcd->cdda_type == CT_WAV) + { + // skip headers, assume it's 44kHz stereo uncompressed + pm_seek(Pico_mcd->cdda_stream, 44, SEEK_CUR); + } +} + + +PICO_INTERNAL void PsndClear(void) +{ + int len = PsndLen; + if (PsndLen_exc_add) len++; + if (PicoOpt & POPT_EN_STEREO) + memset32((int *) PsndOut, 0, len); // assume PsndOut to be aligned + else { + short *out = PsndOut; + if ((long)out & 2) { *out++ = 0; len--; } + memset32((int *) out, 0, len/2); + if (len & 1) out[len-1] = 0; + } +} + + +static int PsndRender(int offset, int length) +{ + int buf32_updated = 0; + int *buf32 = PsndBuffer+offset; + int stereo = (PicoOpt & 8) >> 3; + + offset <<= stereo; + + pprof_start(sound); + +#if !SIMPLE_WRITE_SOUND + if (offset == 0) { // should happen once per frame + // compensate for float part of PsndLen + PsndLen_exc_cnt += PsndLen_exc_add; + if (PsndLen_exc_cnt >= 0x10000) { + PsndLen_exc_cnt -= 0x10000; + length++; + } + } +#endif + + // PSG + if (PicoOpt & POPT_EN_PSG) + SN76496Update(PsndOut+offset, length, stereo); + + if (PicoAHW & PAHW_PICO) { + PicoPicoPCMUpdate(PsndOut+offset, length, stereo); + return length; + } + + // Add in the stereo FM buffer + if (PicoOpt & POPT_EN_FM) { + buf32_updated = YM2612UpdateOne(buf32, length, stereo, 1); + } else + memset32(buf32, 0, length<cdda_stream != NULL + && !(Pico_mcd->s68k_regs[0x36] & 1)) + { + // note: only 44, 22 and 11 kHz supported, with forced stereo + if (Pico_mcd->cdda_type == CT_MP3) + mp3_update(buf32, length, stereo); + else + cdda_raw_update(buf32, length); + } + + if ((PicoAHW & PAHW_32X) && (PicoOpt & POPT_EN_PWM)) + p32x_pwm_update(buf32, length, stereo); + + // convert + limit to normal 16bit output + PsndMix_32_to_16l(PsndOut+offset, buf32, length); + + pprof_end(sound); + + return length; +} + +// to be called on 224 or line_sample scanlines only +PICO_INTERNAL void PsndGetSamples(int y) +{ +#if SIMPLE_WRITE_SOUND + if (y != 224) return; + PsndRender(0, PsndLen); + if (PicoWriteSound) + PicoWriteSound(PsndLen * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2)); + PsndClear(); +#else + static int curr_pos = 0; + + if (y == 224) + { + if (emustatus & 2) + curr_pos += PsndRender(curr_pos, PsndLen-PsndLen/2); + else curr_pos = PsndRender(0, PsndLen); + if (emustatus & 1) + emustatus |= 2; + else emustatus &= ~2; + if (PicoWriteSound) + PicoWriteSound(curr_pos * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2)); + // clear sound buffer + PsndClear(); + } + else if (emustatus & 3) { + emustatus|= 2; + emustatus&=~1; + curr_pos = PsndRender(0, PsndLen/2); + } +#endif +} + +PICO_INTERNAL void PsndGetSamplesMS(void) +{ + int stereo = (PicoOpt & 8) >> 3; + int length = PsndLen; + +#if !SIMPLE_WRITE_SOUND + // compensate for float part of PsndLen + PsndLen_exc_cnt += PsndLen_exc_add; + if (PsndLen_exc_cnt >= 0x10000) { + PsndLen_exc_cnt -= 0x10000; + length++; + } +#endif + + // PSG + if (PicoOpt & POPT_EN_PSG) + SN76496Update(PsndOut, length, stereo); + + // upmix to "stereo" if needed + if (stereo) { + int i, *p; + for (i = length, p = (void *)PsndOut; i > 0; i--, p++) + *p |= *p << 16; + } + + if (PicoWriteSound != NULL) + PicoWriteSound(length * ((PicoOpt & POPT_EN_STEREO) ? 4 : 2)); + PsndClear(); +} + diff --git a/waterbox/picodrive/pico/sound/ym2612.c b/waterbox/picodrive/pico/sound/ym2612.c new file mode 100644 index 0000000000..efe5054e9e --- /dev/null +++ b/waterbox/picodrive/pico/sound/ym2612.c @@ -0,0 +1,2056 @@ +/* +** This is a bunch of remains of original fm.c from MAME project. All stuff +** unrelated to ym2612 was removed, multiple chip support was removed, +** some parts of code were slightly rewritten and tied to the emulator. +** +** SSG-EG was also removed, because it's rarely used, Sega2.doc even does not +** document it ("proprietary") and tells to write 0 to SSG-EG control register. +*/ + +/* +** +** File: fm.c -- software implementation of Yamaha FM sound generator +** +** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net) +** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development +** +** Version 1.4 (final beta) +** +*/ + +/* +** History: +** +** 03-08-2003 Jarek Burczynski: +** - fixed YM2608 initial values (after the reset) +** - fixed flag and irqmask handling (YM2608) +** - fixed BUFRDY flag handling (YM2608) +** +** 14-06-2003 Jarek Burczynski: +** - implemented all of the YM2608 status register flags +** - implemented support for external memory read/write via YM2608 +** - implemented support for deltat memory limit register in YM2608 emulation +** +** 22-05-2003 Jarek Burczynski: +** - fixed LFO PM calculations (copy&paste bugfix) +** +** 08-05-2003 Jarek Burczynski: +** - fixed SSG support +** +** 22-04-2003 Jarek Burczynski: +** - implemented 100% correct LFO generator (verified on real YM2610 and YM2608) +** +** 15-04-2003 Jarek Burczynski: +** - added support for YM2608's register 0x110 - status mask +** +** 01-12-2002 Jarek Burczynski: +** - fixed register addressing in YM2608, YM2610, YM2610B chips. (verified on real YM2608) +** The addressing patch used for early Neo-Geo games can be removed now. +** +** 26-11-2002 Jarek Burczynski, Nicola Salmoria: +** - recreated YM2608 ADPCM ROM using data from real YM2608's output which leads to: +** - added emulation of YM2608 drums. +** - output of YM2608 is two times lower now - same as YM2610 (verified on real YM2608) +** +** 16-08-2002 Jarek Burczynski: +** - binary exact Envelope Generator (verified on real YM2203); +** identical to YM2151 +** - corrected 'off by one' error in feedback calculations (when feedback is off) +** - corrected connection (algorithm) calculation (verified on real YM2203 and YM2610) +** +** 18-12-2001 Jarek Burczynski: +** - added SSG-EG support (verified on real YM2203) +** +** 12-08-2001 Jarek Burczynski: +** - corrected ym_sin_tab and ym_tl_tab data (verified on real chip) +** - corrected feedback calculations (verified on real chip) +** - corrected phase generator calculations (verified on real chip) +** - corrected envelope generator calculations (verified on real chip) +** - corrected FM volume level (YM2610 and YM2610B). +** - changed YMxxxUpdateOne() functions (YM2203, YM2608, YM2610, YM2610B, YM2612) : +** this was needed to calculate YM2610 FM channels output correctly. +** (Each FM channel is calculated as in other chips, but the output of the channel +** gets shifted right by one *before* sending to accumulator. That was impossible to do +** with previous implementation). +** +** 23-07-2001 Jarek Burczynski, Nicola Salmoria: +** - corrected YM2610 ADPCM type A algorithm and tables (verified on real chip) +** +** 11-06-2001 Jarek Burczynski: +** - corrected end of sample bug in ADPCMA_calc_cha(). +** Real YM2610 checks for equality between current and end addresses (only 20 LSB bits). +** +** 08-12-98 hiro-shi: +** rename ADPCMA -> ADPCMB, ADPCMB -> ADPCMA +** move ROM limit check.(CALC_CH? -> 2610Write1/2) +** test program (ADPCMB_TEST) +** move ADPCM A/B end check. +** ADPCMB repeat flag(no check) +** change ADPCM volume rate (8->16) (32->48). +** +** 09-12-98 hiro-shi: +** change ADPCM volume. (8->16, 48->64) +** replace ym2610 ch0/3 (YM-2610B) +** change ADPCM_SHIFT (10->8) missing bank change 0x4000-0xffff. +** add ADPCM_SHIFT_MASK +** change ADPCMA_DECODE_MIN/MAX. +*/ + + + + +/************************************************************************/ +/* comment of hiro-shi(Hiromitsu Shioya) */ +/* YM2610(B) = OPN-B */ +/* YM2610 : PSG:3ch FM:4ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/* YM2610B : PSG:3ch FM:6ch ADPCM(18.5KHz):6ch DeltaT ADPCM:1ch */ +/************************************************************************/ + +//#include + +#include +#include + +#include "ym2612.h" + +#ifndef EXTERNAL_YM2612 +#include +// let it be 1 global to simplify things +YM2612 ym2612; + +#else +extern YM2612 *ym2612_940; +#define ym2612 (*ym2612_940) + +#endif + +void memset32(int *dest, int c, int count); + + +#ifndef __GNUC__ +#pragma warning (disable:4100) // unreferenced formal parameter +#pragma warning (disable:4244) +#pragma warning (disable:4245) // signed/unsigned in conversion +#pragma warning (disable:4710) +#pragma warning (disable:4018) // signed/unsigned +#endif + +#ifndef INLINE +#define INLINE static __inline +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +/* globals */ + +#define FREQ_SH 16 /* 16.16 fixed point (frequency calculations) */ +#define EG_SH 16 /* 16.16 fixed point (envelope generator timing) */ +#define LFO_SH 25 /* 7.25 fixed point (LFO calculations) */ +#define TIMER_SH 16 /* 16.16 fixed point (timers calculations) */ + +#define ENV_BITS 10 +#define ENV_LEN (1< max ) val = max; \ + else if ( val < min ) val = min; \ +} + + +/* TL_TAB_LEN is calculated as: +* 13 - sinus amplitude bits (Y axis) +* 2 - sinus sign bit (Y axis) +* TL_RES_LEN - sinus resolution (X axis) +*/ +//#define TL_TAB_LEN (13*2*TL_RES_LEN) +#define TL_TAB_LEN (13*TL_RES_LEN*256/8) // 106496*2 +UINT16 ym_tl_tab[TL_TAB_LEN]; + +/* ~3K wasted but oh well */ +UINT16 ym_tl_tab2[13*TL_RES_LEN]; + +#define ENV_QUIET (2*13*TL_RES_LEN/8) + +/* sin waveform table in 'decibel' scale (use only period/4 values) */ +static UINT16 ym_sin_tab[256]; + +/* sustain level table (3dB per step) */ +/* bit0, bit1, bit2, bit3, bit4, bit5, bit6 */ +/* 1, 2, 4, 8, 16, 32, 64 (value)*/ +/* 0.75, 1.5, 3, 6, 12, 24, 48 (dB)*/ + +/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/ +#define SC(db) (UINT32) ( db * (4.0/ENV_STEP) ) +static const UINT32 sl_table[16]={ + SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7), + SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31) +}; +#undef SC + + +#if 0 +#define RATE_STEPS (8) +static const UINT8 eg_inc[19*RATE_STEPS]={ + +/*cycle:0 1 2 3 4 5 6 7*/ + +/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..11 0 (increment by 0 or 1) */ +/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..11 1 */ +/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..11 2 */ +/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..11 3 */ + +/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 12 0 (increment by 1) */ +/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 12 1 */ +/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 12 2 */ +/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 12 3 */ + +/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 13 0 (increment by 2) */ +/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 13 1 */ +/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 13 2 */ +/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 13 3 */ + +/*12 */ 4,4, 4,4, 4,4, 4,4, /* rate 14 0 (increment by 4) */ +/*13 */ 4,4, 4,8, 4,4, 4,8, /* rate 14 1 */ +/*14 */ 4,8, 4,8, 4,8, 4,8, /* rate 14 2 */ +/*15 */ 4,8, 8,8, 4,8, 8,8, /* rate 14 3 */ + +/*16 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ +/*17 */ 16,16,16,16,16,16,16,16, /* rates 15 2, 15 3 for attack */ +/*18 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */ +}; +#endif + + +#define PACK(a0,a1,a2,a3,a4,a5,a6,a7) ((a7<<21)|(a6<<18)|(a5<<15)|(a4<<12)|(a3<<9)|(a2<<6)|(a1<<3)|(a0<<0)) +static const UINT32 eg_inc_pack[19] = +{ +/* 0 */ PACK(0,1,0,1,0,1,0,1), /* rates 00..11 0 (increment by 0 or 1) */ +/* 1 */ PACK(0,1,0,1,1,1,0,1), /* rates 00..11 1 */ +/* 2 */ PACK(0,1,1,1,0,1,1,1), /* rates 00..11 2 */ +/* 3 */ PACK(0,1,1,1,1,1,1,1), /* rates 00..11 3 */ + +/* 4 */ PACK(1,1,1,1,1,1,1,1), /* rate 12 0 (increment by 1) */ +/* 5 */ PACK(1,1,1,2,1,1,1,2), /* rate 12 1 */ +/* 6 */ PACK(1,2,1,2,1,2,1,2), /* rate 12 2 */ +/* 7 */ PACK(1,2,2,2,1,2,2,2), /* rate 12 3 */ + +/* 8 */ PACK(2,2,2,2,2,2,2,2), /* rate 13 0 (increment by 2) */ +/* 9 */ PACK(2,2,2,3,2,2,2,3), /* rate 13 1 */ +/*10 */ PACK(2,3,2,3,2,3,2,3), /* rate 13 2 */ +/*11 */ PACK(2,3,3,3,2,3,3,3), /* rate 13 3 */ + +/*12 */ PACK(3,3,3,3,3,3,3,3), /* rate 14 0 (increment by 4) */ +/*13 */ PACK(3,3,3,4,3,3,3,4), /* rate 14 1 */ +/*14 */ PACK(3,4,3,4,3,4,3,4), /* rate 14 2 */ +/*15 */ PACK(3,4,4,4,3,4,4,4), /* rate 14 3 */ + +/*16 */ PACK(4,4,4,4,4,4,4,4), /* rates 15 0, 15 1, 15 2, 15 3 (increment by 8) */ +/*17 */ PACK(5,5,5,5,5,5,5,5), /* rates 15 2, 15 3 for attack */ +/*18 */ PACK(0,0,0,0,0,0,0,0), /* infinity rates for attack and decay(s) */ +}; + + +//#define O(a) (a*RATE_STEPS) +#define O(a) a + +/*note that there is no O(17) in this table - it's directly in the code */ +static const UINT8 eg_rate_select[32+64+32]={ /* Envelope Generator rates (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), +O(18),O(18),O(18),O(18),O(18),O(18),O(18),O(18), + +/* rates 00-11 */ +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), +O( 0),O( 1),O( 2),O( 3), + +/* rate 12 */ +O( 4),O( 5),O( 6),O( 7), + +/* rate 13 */ +O( 8),O( 9),O(10),O(11), + +/* rate 14 */ +O(12),O(13),O(14),O(15), + +/* rate 15 */ +O(16),O(16),O(16),O(16), + +/* 32 dummy rates (same as 15 3) */ +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16), +O(16),O(16),O(16),O(16),O(16),O(16),O(16),O(16) + +}; +#undef O + +/*rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15*/ +/*shift 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0 */ +/*mask 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0, 0, 0 */ + +#define O(a) (a*1) +static const UINT8 eg_rate_shift[32+64+32]={ /* Envelope Generator counter shifts (32 + 64 rates + 32 RKS) */ +/* 32 infinite time rates */ +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), +O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0), + +/* rates 00-11 */ +O(11),O(11),O(11),O(11), +O(10),O(10),O(10),O(10), +O( 9),O( 9),O( 9),O( 9), +O( 8),O( 8),O( 8),O( 8), +O( 7),O( 7),O( 7),O( 7), +O( 6),O( 6),O( 6),O( 6), +O( 5),O( 5),O( 5),O( 5), +O( 4),O( 4),O( 4),O( 4), +O( 3),O( 3),O( 3),O( 3), +O( 2),O( 2),O( 2),O( 2), +O( 1),O( 1),O( 1),O( 1), +O( 0),O( 0),O( 0),O( 0), + +/* rate 12 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 13 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 14 */ +O( 0),O( 0),O( 0),O( 0), + +/* rate 15 */ +O( 0),O( 0),O( 0),O( 0), + +/* 32 dummy rates (same as 15 3) */ +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), +O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0) + +}; +#undef O + +static const UINT8 dt_tab[4 * 32]={ +/* this is YM2151 and YM2612 phase increment data (in 10.10 fixed point format)*/ +/* FD=0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/* FD=1 */ + 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 8, 8, 8, 8, +/* FD=2 */ + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, + 5, 6, 6, 7, 8, 8, 9,10,11,12,13,14,16,16,16,16, +/* FD=3 */ + 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, + 8 ,8, 9,10,11,12,13,14,16,17,19,20,22,22,22,22 +}; + + +/* OPN key frequency number -> key code follow table */ +/* fnum higher 4bit -> keycode lower 2bit */ +static const UINT8 opn_fktable[16] = {0,0,0,0,0,0,0,1,2,3,3,3,3,3,3,3}; + + +/* 8 LFO speed parameters */ +/* each value represents number of samples that one LFO level will last for */ +static const UINT32 lfo_samples_per_step[8] = {108, 77, 71, 67, 62, 44, 8, 5}; + + + +/*There are 4 different LFO AM depths available, they are: + 0 dB, 1.4 dB, 5.9 dB, 11.8 dB + Here is how it is generated (in EG steps): + + 11.8 dB = 0, 2, 4, 6, 8, 10,12,14,16...126,126,124,122,120,118,....4,2,0 + 5.9 dB = 0, 1, 2, 3, 4, 5, 6, 7, 8....63, 63, 62, 61, 60, 59,.....2,1,0 + 1.4 dB = 0, 0, 0, 0, 1, 1, 1, 1, 2,...15, 15, 15, 15, 14, 14,.....0,0,0 + + (1.4 dB is loosing precision as you can see) + + It's implemented as generator from 0..126 with step 2 then a shift + right N times, where N is: + 8 for 0 dB + 3 for 1.4 dB + 1 for 5.9 dB + 0 for 11.8 dB +*/ +static const UINT8 lfo_ams_depth_shift[4] = {8, 3, 1, 0}; + + + +/*There are 8 different LFO PM depths available, they are: + 0, 3.4, 6.7, 10, 14, 20, 40, 80 (cents) + + Modulation level at each depth depends on F-NUMBER bits: 4,5,6,7,8,9,10 + (bits 8,9,10 = FNUM MSB from OCT/FNUM register) + + Here we store only first quarter (positive one) of full waveform. + Full table (lfo_pm_table) containing all 128 waveforms is build + at run (init) time. + + One value in table below represents 4 (four) basic LFO steps + (1 PM step = 4 AM steps). + + For example: + at LFO SPEED=0 (which is 108 samples per basic LFO step) + one value from "lfo_pm_output" table lasts for 432 consecutive + samples (4*108=432) and one full LFO waveform cycle lasts for 13824 + samples (32*432=13824; 32 because we store only a quarter of whole + waveform in the table below) +*/ +static const UINT8 lfo_pm_output[7*8][8]={ /* 7 bits meaningful (of F-NUMBER), 8 LFO output levels per one depth (out of 32), 8 LFO depths */ +/* FNUM BIT 4: 000 0001xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 7 */ {0, 0, 0, 0, 1, 1, 1, 1}, + +/* FNUM BIT 5: 000 0010xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 5 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 6 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 7 */ {0, 0, 1, 1, 2, 2, 2, 3}, + +/* FNUM BIT 6: 000 0100xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 4 */ {0, 0, 0, 0, 0, 0, 0, 1}, +/* DEPTH 5 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 6 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 7 */ {0, 0, 2, 3, 4, 4, 5, 6}, + +/* FNUM BIT 7: 000 1000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 2 */ {0, 0, 0, 0, 0, 0, 1, 1}, +/* DEPTH 3 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 4 */ {0, 0, 0, 1, 1, 1, 1, 2}, +/* DEPTH 5 */ {0, 0, 1, 1, 2, 2, 2, 3}, +/* DEPTH 6 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 7 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, + +/* FNUM BIT 8: 001 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 1, 1, 1, 1}, +/* DEPTH 2 */ {0, 0, 0, 1, 1, 1, 2, 2}, +/* DEPTH 3 */ {0, 0, 1, 1, 2, 2, 3, 3}, +/* DEPTH 4 */ {0, 0, 1, 2, 2, 2, 3, 4}, +/* DEPTH 5 */ {0, 0, 2, 3, 4, 4, 5, 6}, +/* DEPTH 6 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 7 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, + +/* FNUM BIT 9: 010 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 2, 2, 2, 2}, +/* DEPTH 2 */ {0, 0, 0, 2, 2, 2, 4, 4}, +/* DEPTH 3 */ {0, 0, 2, 2, 4, 4, 6, 6}, +/* DEPTH 4 */ {0, 0, 2, 4, 4, 4, 6, 8}, +/* DEPTH 5 */ {0, 0, 4, 6, 8, 8, 0xa, 0xc}, +/* DEPTH 6 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 7 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, + +/* FNUM BIT10: 100 0000xxxx */ +/* DEPTH 0 */ {0, 0, 0, 0, 0, 0, 0, 0}, +/* DEPTH 1 */ {0, 0, 0, 0, 4, 4, 4, 4}, +/* DEPTH 2 */ {0, 0, 0, 4, 4, 4, 8, 8}, +/* DEPTH 3 */ {0, 0, 4, 4, 8, 8, 0xc, 0xc}, +/* DEPTH 4 */ {0, 0, 4, 8, 8, 8, 0xc,0x10}, +/* DEPTH 5 */ {0, 0, 8, 0xc,0x10,0x10,0x14,0x18}, +/* DEPTH 6 */ {0, 0,0x10,0x18,0x20,0x20,0x28,0x30}, +/* DEPTH 7 */ {0, 0,0x20,0x30,0x40,0x40,0x50,0x60}, + +}; + +/* all 128 LFO PM waveforms */ +static INT32 lfo_pm_table[128*8*32]; /* 128 combinations of 7 bits meaningful (of F-NUMBER), 8 LFO depths, 32 LFO output levels per one depth */ + +/* there are 2048 FNUMs that can be generated using FNUM/BLK registers + but LFO works with one more bit of a precision so we really need 4096 elements */ +static UINT32 fn_table[4096]; /* fnumber->increment counter */ + +static int g_lfo_ampm = 0; + +/* register number to channel number , slot offset */ +#define OPN_CHAN(N) (N&3) +#define OPN_SLOT(N) ((N>>2)&3) + +/* slot number */ +#define SLOT1 0 +#define SLOT2 2 +#define SLOT3 1 +#define SLOT4 3 + + +/* OPN Mode Register Write */ +INLINE void set_timers( int v ) +{ + /* b7 = CSM MODE */ + /* b6 = 3 slot mode */ + /* b5 = reset b */ + /* b4 = reset a */ + /* b3 = timer enable b */ + /* b2 = timer enable a */ + /* b1 = load b */ + /* b0 = load a */ + ym2612.OPN.ST.mode = v; + + /* reset Timer b flag */ + if( v & 0x20 ) + ym2612.OPN.ST.status &= ~2; + + /* reset Timer a flag */ + if( v & 0x10 ) + ym2612.OPN.ST.status &= ~1; +} + + +INLINE void FM_KEYON(int c , int s ) +{ + FM_SLOT *SLOT = &ym2612.CH[c].SLOT[s]; + if( !SLOT->key ) + { + SLOT->key = 1; + SLOT->phase = 0; /* restart Phase Generator */ + SLOT->state = EG_ATT; /* phase -> Attack */ + ym2612.slot_mask |= (1<key ) + { + SLOT->key = 0; + if (SLOT->state>EG_REL) + SLOT->state = EG_REL;/* phase -> Release */ + } +} + + +/* set detune & multiple */ +INLINE void set_det_mul(FM_CH *CH, FM_SLOT *SLOT, int v) +{ + SLOT->mul = (v&0x0f)? (v&0x0f)*2 : 1; + SLOT->DT = ym2612.OPN.ST.dt_tab[(v>>4)&7]; + CH->SLOT[SLOT1].Incr=-1; +} + +/* set total level */ +INLINE void set_tl(FM_SLOT *SLOT, int v) +{ + SLOT->tl = (v&0x7f)<<(ENV_BITS-7); /* 7bit TL */ +} + +/* set attack rate & key scale */ +INLINE void set_ar_ksr(FM_CH *CH, FM_SLOT *SLOT, int v) +{ + UINT8 old_KSR = SLOT->KSR; + + SLOT->ar = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + SLOT->KSR = 3-(v>>6); + if (SLOT->KSR != old_KSR) + { + CH->SLOT[SLOT1].Incr=-1; + } + else + { + int eg_sh_ar, eg_sel_ar; + + /* refresh Attack rate */ + if ((SLOT->ar + SLOT->ksr) < 32+62) + { + eg_sh_ar = eg_rate_shift [SLOT->ar + SLOT->ksr ]; + eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ]; + } + else + { + eg_sh_ar = 0; + eg_sel_ar = 17; + } + + SLOT->eg_pack_ar = eg_inc_pack[eg_sel_ar] | (eg_sh_ar<<24); + } +} + +/* set decay rate */ +INLINE void set_dr(FM_SLOT *SLOT, int v) +{ + int eg_sh_d1r, eg_sel_d1r; + + SLOT->d1r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + eg_sh_d1r = eg_rate_shift [SLOT->d1r + SLOT->ksr]; + eg_sel_d1r= eg_rate_select[SLOT->d1r + SLOT->ksr]; + + SLOT->eg_pack_d1r = eg_inc_pack[eg_sel_d1r] | (eg_sh_d1r<<24); +} + +/* set sustain rate */ +INLINE void set_sr(FM_SLOT *SLOT, int v) +{ + int eg_sh_d2r, eg_sel_d2r; + + SLOT->d2r = (v&0x1f) ? 32 + ((v&0x1f)<<1) : 0; + + eg_sh_d2r = eg_rate_shift [SLOT->d2r + SLOT->ksr]; + eg_sel_d2r= eg_rate_select[SLOT->d2r + SLOT->ksr]; + + SLOT->eg_pack_d2r = eg_inc_pack[eg_sel_d2r] | (eg_sh_d2r<<24); +} + +/* set release rate */ +INLINE void set_sl_rr(FM_SLOT *SLOT, int v) +{ + int eg_sh_rr, eg_sel_rr; + + SLOT->sl = sl_table[ v>>4 ]; + + SLOT->rr = 34 + ((v&0x0f)<<2); + + eg_sh_rr = eg_rate_shift [SLOT->rr + SLOT->ksr]; + eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr]; + + SLOT->eg_pack_rr = eg_inc_pack[eg_sel_rr] | (eg_sh_rr<<24); +} + + + +INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm) +{ + int ret, sin = (phase>>16) + (pm>>1); + int neg = sin & 0x200; + if (sin & 0x100) sin ^= 0xff; + sin&=0xff; + env&=~1; + + // this was already checked + // if (env >= ENV_QUIET) // 384 + // return 0; + + ret = ym_tl_tab[sin | (env<<7)]; + + return neg ? -ret : ret; +} + +INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm) +{ + int ret, sin = (phase+pm)>>16; + int neg = sin & 0x200; + if (sin & 0x100) sin ^= 0xff; + sin&=0xff; + env&=~1; + + // if (env >= ENV_QUIET) // 384 + // return 0; + + ret = ym_tl_tab[sin | (env<<7)]; + + return neg ? -ret : ret; +} + +#if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612) +/* advance LFO to next sample */ +INLINE int advance_lfo(int lfo_ampm, UINT32 lfo_cnt_old, UINT32 lfo_cnt) +{ + UINT8 pos; + UINT8 prev_pos; + + prev_pos = (lfo_cnt_old >> LFO_SH) & 127; + + pos = (lfo_cnt >> LFO_SH) & 127; + + /* update AM when LFO output changes */ + + if (prev_pos != pos) + { + lfo_ampm &= 0xff; + /* triangle */ + /* AM: 0 to 126 step +2, 126 to 0 step -2 */ + if (pos<64) + lfo_ampm |= ((pos&63) * 2) << 8; /* 0 - 126 */ + else + lfo_ampm |= (126 - (pos&63)*2) << 8; + } + else + { + return lfo_ampm; + } + + /* PM works with 4 times slower clock */ + prev_pos >>= 2; + pos >>= 2; + /* update PM when LFO output changes */ + if (prev_pos != pos) + { + lfo_ampm &= ~0xff; + lfo_ampm |= pos; /* 0 - 32 */ + } + return lfo_ampm; +} + +#define EG_INC_VAL() \ + ((1 << ((pack >> ((eg_cnt>>shift)&7)*3)&7)) >> 1) + +INLINE UINT32 update_eg_phase(FM_SLOT *SLOT, UINT32 eg_cnt) +{ + INT32 volume = SLOT->volume; + + switch(SLOT->state) + { + case EG_ATT: /* attack phase */ + { + UINT32 pack = SLOT->eg_pack_ar; + UINT32 shift = pack>>24; + if ( !(eg_cnt & ((1<>4; + + if (volume <= MIN_ATT_INDEX) + { + volume = MIN_ATT_INDEX; + SLOT->state = EG_DEC; + } + } + break; + } + + case EG_DEC: /* decay phase */ + { + UINT32 pack = SLOT->eg_pack_d1r; + UINT32 shift = pack>>24; + if ( !(eg_cnt & ((1<= (INT32) SLOT->sl ) + SLOT->state = EG_SUS; + } + break; + } + + case EG_SUS: /* sustain phase */ + { + UINT32 pack = SLOT->eg_pack_d2r; + UINT32 shift = pack>>24; + if ( !(eg_cnt & ((1<= MAX_ATT_INDEX ) + { + volume = MAX_ATT_INDEX; + /* do not change SLOT->state (verified on real chip) */ + } + } + break; + } + + case EG_REL: /* release phase */ + { + UINT32 pack = SLOT->eg_pack_rr; + UINT32 shift = pack>>24; + if ( !(eg_cnt & ((1<= MAX_ATT_INDEX ) + { + volume = MAX_ATT_INDEX; + SLOT->state = EG_OFF; + } + } + break; + } + } + + SLOT->volume = volume; + return SLOT->tl + ((UINT32)volume); /* tl is 7bit<<3, volume 0-1023 (0-2039 total) */ +} +#endif + + +typedef struct +{ + UINT16 vol_out1; /* 00: current output from EG circuit (without AM from LFO) */ + UINT16 vol_out2; + UINT16 vol_out3; + UINT16 vol_out4; + UINT32 pad[2]; + UINT32 phase1; /* 10 */ + UINT32 phase2; + UINT32 phase3; + UINT32 phase4; + UINT32 incr1; /* 20: phase step */ + UINT32 incr2; + UINT32 incr3; + UINT32 incr4; + UINT32 lfo_cnt; /* 30 */ + UINT32 lfo_inc; + INT32 mem; /* one sample delay memory */ + UINT32 eg_cnt; /* envelope generator counter */ + FM_CH *CH; /* 40: envelope generator counter */ + UINT32 eg_timer; + UINT32 eg_timer_add; + UINT32 pack; // 4c: stereo, lastchan, disabled, lfo_enabled | pan_r, pan_l, ams[2] | AMmasks[4] | FB[4] | lfo_ampm[16] + UINT32 algo; /* 50: algo[3], was_update */ + INT32 op1_out; +#ifdef _MIPS_ARCH_ALLEGREX + UINT32 pad1[3+8]; +#endif +} chan_rend_context; + + +#if !defined(_ASM_YM2612_C) || defined(EXTERNAL_YM2612) +static void chan_render_loop(chan_rend_context *ct, int *buffer, int length) +{ + int scounter; /* sample counter */ + + /* sample generating loop */ + for (scounter = 0; scounter < length; scounter++) + { + int smp = 0; /* produced sample */ + unsigned int eg_out, eg_out2, eg_out4; + + if (ct->pack & 8) { /* LFO enabled ? (test Earthworm Jim in between demo 1 and 2) */ + ct->pack = (ct->pack&0xffff) | (advance_lfo(ct->pack >> 16, ct->lfo_cnt, ct->lfo_cnt + ct->lfo_inc) << 16); + ct->lfo_cnt += ct->lfo_inc; + } + + ct->eg_timer += ct->eg_timer_add; + while (ct->eg_timer >= EG_TIMER_OVERFLOW) + { + ct->eg_timer -= EG_TIMER_OVERFLOW; + ct->eg_cnt++; + + if (ct->CH->SLOT[SLOT1].state != EG_OFF) ct->vol_out1 = update_eg_phase(&ct->CH->SLOT[SLOT1], ct->eg_cnt); + if (ct->CH->SLOT[SLOT2].state != EG_OFF) ct->vol_out2 = update_eg_phase(&ct->CH->SLOT[SLOT2], ct->eg_cnt); + if (ct->CH->SLOT[SLOT3].state != EG_OFF) ct->vol_out3 = update_eg_phase(&ct->CH->SLOT[SLOT3], ct->eg_cnt); + if (ct->CH->SLOT[SLOT4].state != EG_OFF) ct->vol_out4 = update_eg_phase(&ct->CH->SLOT[SLOT4], ct->eg_cnt); + } + + if (ct->pack & 4) continue; /* output disabled */ + + /* calculate channel sample */ + eg_out = ct->vol_out1; + if ( (ct->pack & 8) && (ct->pack&(1<<(SLOT1+8))) ) eg_out += ct->pack >> (((ct->pack&0xc0)>>6)+24); + + if( eg_out < ENV_QUIET ) /* SLOT 1 */ + { + int out = 0; + + if (ct->pack&0xf000) out = ((ct->op1_out>>16) + ((ct->op1_out<<16)>>16)) << ((ct->pack&0xf000)>>12); /* op1_out0 + op1_out1 */ + ct->op1_out <<= 16; + ct->op1_out |= (unsigned short)op_calc1(ct->phase1, eg_out, out); + } else { + ct->op1_out <<= 16; /* op1_out0 = op1_out1; op1_out1 = 0; */ + } + + eg_out = ct->vol_out3; // volume_calc(&CH->SLOT[SLOT3]); + eg_out2 = ct->vol_out2; // volume_calc(&CH->SLOT[SLOT2]); + eg_out4 = ct->vol_out4; // volume_calc(&CH->SLOT[SLOT4]); + + if (ct->pack & 8) { + unsigned int add = ct->pack >> (((ct->pack&0xc0)>>6)+24); + if (ct->pack & (1<<(SLOT3+8))) eg_out += add; + if (ct->pack & (1<<(SLOT2+8))) eg_out2 += add; + if (ct->pack & (1<<(SLOT4+8))) eg_out4 += add; + } + + switch( ct->CH->ALGO ) + { + case 0: + { + /* M1---C1---MEM---M2---C2---OUT */ + int m2,c1,c2=0; /* Phase Modulation input for operators 2,3,4 */ + m2 = ct->mem; + c1 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 = op_calc(ct->phase3, eg_out, m2); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, c1); + } + else ct->mem = 0; + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 1: + { + /* M1------+-MEM---M2---C2---OUT */ + /* C1-+ */ + int m2,c2=0; + m2 = ct->mem; + ct->mem = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 = op_calc(ct->phase3, eg_out, m2); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem+= op_calc(ct->phase2, eg_out2, 0); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 2: + { + /* M1-----------------+-C2---OUT */ + /* C1---MEM---M2-+ */ + int m2,c2; + m2 = ct->mem; + c2 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 += op_calc(ct->phase3, eg_out, m2); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, 0); + } + else ct->mem = 0; + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 3: + { + /* M1---C1---MEM------+-C2---OUT */ + /* M2-+ */ + int c1,c2; + c2 = ct->mem; + c1 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 += op_calc(ct->phase3, eg_out, 0); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + ct->mem = op_calc(ct->phase2, eg_out2, c1); + } + else ct->mem = 0; + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp = op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 4: + { + /* M1---C1-+-OUT */ + /* M2---C2-+ */ + /* MEM: not used */ + int c1,c2=0; + c1 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + c2 = op_calc(ct->phase3, eg_out, 0); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp = op_calc(ct->phase2, eg_out2, c1); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 5: + { + /* +----C1----+ */ + /* M1-+-MEM---M2-+-OUT */ + /* +----C2----+ */ + int m2,c1,c2; + m2 = ct->mem; + ct->mem = c1 = c2 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp = op_calc(ct->phase3, eg_out, m2); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp+= op_calc(ct->phase2, eg_out2, c1); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, c2); + } + break; + } + case 6: + { + /* M1---C1-+ */ + /* M2-+-OUT */ + /* C2-+ */ + /* MEM: not used */ + int c1; + c1 = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp = op_calc(ct->phase3, eg_out, 0); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp+= op_calc(ct->phase2, eg_out2, c1); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp+= op_calc(ct->phase4, eg_out4, 0); + } + break; + } + case 7: + { + /* M1-+ */ + /* C1-+-OUT */ + /* M2-+ */ + /* C2-+ */ + /* MEM: not used*/ + smp = ct->op1_out>>16; + if( eg_out < ENV_QUIET ) { /* SLOT 3 */ + smp += op_calc(ct->phase3, eg_out, 0); + } + if( eg_out2 < ENV_QUIET ) { /* SLOT 2 */ + smp += op_calc(ct->phase2, eg_out2, 0); + } + if( eg_out4 < ENV_QUIET ) { /* SLOT 4 */ + smp += op_calc(ct->phase4, eg_out4, 0); + } + break; + } + } + /* done calculating channel sample */ + + /* mix sample to output buffer */ + if (smp) { + if (ct->pack & 1) { /* stereo */ + if (ct->pack & 0x20) /* L */ /* TODO: check correctness */ + buffer[scounter*2] += smp; + if (ct->pack & 0x10) /* R */ + buffer[scounter*2+1] += smp; + } else { + buffer[scounter] += smp; + } + ct->algo = 8; // algo is only used in asm, here only bit3 is used + } + + /* update phase counters AFTER output calculations */ + ct->phase1 += ct->incr1; + ct->phase2 += ct->incr2; + ct->phase3 += ct->incr3; + ct->phase4 += ct->incr4; + } +} +#else +void chan_render_loop(chan_rend_context *ct, int *buffer, unsigned short length); +#endif + +static chan_rend_context crct; + +static void chan_render_prep(void) +{ + crct.eg_timer_add = ym2612.OPN.eg_timer_add; + crct.lfo_inc = ym2612.OPN.lfo_inc; +} + +static void chan_render_finish(void) +{ + ym2612.OPN.eg_cnt = crct.eg_cnt; + ym2612.OPN.eg_timer = crct.eg_timer; + g_lfo_ampm = crct.pack >> 16; // need_save + ym2612.OPN.lfo_cnt = crct.lfo_cnt; +} + +static int chan_render(int *buffer, int length, int c, UINT32 flags) // flags: stereo, ?, disabled, ?, pan_r, pan_l +{ + crct.CH = &ym2612.CH[c]; + crct.mem = crct.CH->mem_value; /* one sample delay memory */ + crct.lfo_cnt = ym2612.OPN.lfo_cnt; + + flags &= 0x35; + + if (crct.lfo_inc) { + flags |= 8; + flags |= g_lfo_ampm << 16; + flags |= crct.CH->AMmasks << 8; + if (crct.CH->ams == 8) // no ams + flags &= ~0xf00; + else flags |= (crct.CH->ams&3)<<6; + } + flags |= (crct.CH->FB&0xf)<<12; /* feedback shift */ + crct.pack = flags; + + crct.eg_cnt = ym2612.OPN.eg_cnt; /* envelope generator counter */ + crct.eg_timer = ym2612.OPN.eg_timer; + + /* precalculate phase modulation incr */ + crct.phase1 = crct.CH->SLOT[SLOT1].phase; + crct.phase2 = crct.CH->SLOT[SLOT2].phase; + crct.phase3 = crct.CH->SLOT[SLOT3].phase; + crct.phase4 = crct.CH->SLOT[SLOT4].phase; + + /* current output from EG circuit (without AM from LFO) */ + crct.vol_out1 = crct.CH->SLOT[SLOT1].tl + ((UINT32)crct.CH->SLOT[SLOT1].volume); + crct.vol_out2 = crct.CH->SLOT[SLOT2].tl + ((UINT32)crct.CH->SLOT[SLOT2].volume); + crct.vol_out3 = crct.CH->SLOT[SLOT3].tl + ((UINT32)crct.CH->SLOT[SLOT3].volume); + crct.vol_out4 = crct.CH->SLOT[SLOT4].tl + ((UINT32)crct.CH->SLOT[SLOT4].volume); + + crct.op1_out = crct.CH->op1_out; + crct.algo = crct.CH->ALGO & 7; + + if(crct.CH->pms) + { + /* add support for 3 slot mode */ + UINT32 block_fnum = crct.CH->block_fnum; + + UINT32 fnum_lfo = ((block_fnum & 0x7f0) >> 4) * 32 * 8; + INT32 lfo_fn_table_index_offset = lfo_pm_table[ fnum_lfo + crct.CH->pms + ((crct.pack>>16)&0xff) ]; + + if (lfo_fn_table_index_offset) /* LFO phase modulation active */ + { + UINT8 blk; + UINT32 fn; + int kc,fc; + + blk = block_fnum >> 11; + block_fnum = block_fnum*2 + lfo_fn_table_index_offset; + + fn = block_fnum & 0xfff; + + /* keyscale code */ + kc = (blk<<2) | opn_fktable[fn >> 8]; + /* phase increment counter */ + fc = fn_table[fn]>>(7-blk); + + crct.incr1 = ((fc+crct.CH->SLOT[SLOT1].DT[kc])*crct.CH->SLOT[SLOT1].mul) >> 1; + crct.incr2 = ((fc+crct.CH->SLOT[SLOT2].DT[kc])*crct.CH->SLOT[SLOT2].mul) >> 1; + crct.incr3 = ((fc+crct.CH->SLOT[SLOT3].DT[kc])*crct.CH->SLOT[SLOT3].mul) >> 1; + crct.incr4 = ((fc+crct.CH->SLOT[SLOT4].DT[kc])*crct.CH->SLOT[SLOT4].mul) >> 1; + } + else /* LFO phase modulation = zero */ + { + crct.incr1 = crct.CH->SLOT[SLOT1].Incr; + crct.incr2 = crct.CH->SLOT[SLOT2].Incr; + crct.incr3 = crct.CH->SLOT[SLOT3].Incr; + crct.incr4 = crct.CH->SLOT[SLOT4].Incr; + } + } + else /* no LFO phase modulation */ + { + crct.incr1 = crct.CH->SLOT[SLOT1].Incr; + crct.incr2 = crct.CH->SLOT[SLOT2].Incr; + crct.incr3 = crct.CH->SLOT[SLOT3].Incr; + crct.incr4 = crct.CH->SLOT[SLOT4].Incr; + } + + chan_render_loop(&crct, buffer, length); + + crct.CH->op1_out = crct.op1_out; + crct.CH->mem_value = crct.mem; + if (crct.CH->SLOT[SLOT1].state | crct.CH->SLOT[SLOT2].state | crct.CH->SLOT[SLOT3].state | crct.CH->SLOT[SLOT4].state) + { + crct.CH->SLOT[SLOT1].phase = crct.phase1; + crct.CH->SLOT[SLOT2].phase = crct.phase2; + crct.CH->SLOT[SLOT3].phase = crct.phase3; + crct.CH->SLOT[SLOT4].phase = crct.phase4; + } + else + ym2612.slot_mask &= ~(0xf << (c*4)); + + return (crct.algo & 8) >> 3; // had output +} + +/* update phase increment and envelope generator */ +INLINE void refresh_fc_eg_slot(FM_SLOT *SLOT, int fc, int kc) +{ + int ksr, fdt; + + /* (frequency) phase increment counter */ + fdt = fc+SLOT->DT[kc]; + /* detect overflow */ +// if (fdt < 0) fdt += fn_table[0x7ff*2] >> (7-blk-1); + if (fdt < 0) fdt += fn_table[0x7ff*2] >> 2; + SLOT->Incr = fdt*SLOT->mul >> 1; + + ksr = kc >> SLOT->KSR; + if( SLOT->ksr != ksr ) + { + int eg_sh, eg_sel; + SLOT->ksr = ksr; + + /* calculate envelope generator rates */ + if ((SLOT->ar + ksr) < 32+62) + { + eg_sh = eg_rate_shift [SLOT->ar + ksr ]; + eg_sel = eg_rate_select[SLOT->ar + ksr ]; + } + else + { + eg_sh = 0; + eg_sel = 17; + } + + SLOT->eg_pack_ar = eg_inc_pack[eg_sel] | (eg_sh<<24); + + eg_sh = eg_rate_shift [SLOT->d1r + ksr]; + eg_sel = eg_rate_select[SLOT->d1r + ksr]; + + SLOT->eg_pack_d1r = eg_inc_pack[eg_sel] | (eg_sh<<24); + + eg_sh = eg_rate_shift [SLOT->d2r + ksr]; + eg_sel = eg_rate_select[SLOT->d2r + ksr]; + + SLOT->eg_pack_d2r = eg_inc_pack[eg_sel] | (eg_sh<<24); + + eg_sh = eg_rate_shift [SLOT->rr + ksr]; + eg_sel = eg_rate_select[SLOT->rr + ksr]; + + SLOT->eg_pack_rr = eg_inc_pack[eg_sel] | (eg_sh<<24); + } +} + +/* update phase increment counters */ +INLINE void refresh_fc_eg_chan(FM_CH *CH) +{ + if( CH->SLOT[SLOT1].Incr==-1){ + int fc = CH->fc; + int kc = CH->kcode; + refresh_fc_eg_slot(&CH->SLOT[SLOT1] , fc , kc ); + refresh_fc_eg_slot(&CH->SLOT[SLOT2] , fc , kc ); + refresh_fc_eg_slot(&CH->SLOT[SLOT3] , fc , kc ); + refresh_fc_eg_slot(&CH->SLOT[SLOT4] , fc , kc ); + } +} + +INLINE void refresh_fc_eg_chan_sl3(void) +{ + if( ym2612.CH[2].SLOT[SLOT1].Incr==-1) + { + refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT1], ym2612.OPN.SL3.fc[1], ym2612.OPN.SL3.kcode[1] ); + refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT2], ym2612.OPN.SL3.fc[2], ym2612.OPN.SL3.kcode[2] ); + refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT3], ym2612.OPN.SL3.fc[0], ym2612.OPN.SL3.kcode[0] ); + refresh_fc_eg_slot(&ym2612.CH[2].SLOT[SLOT4], ym2612.CH[2].fc , ym2612.CH[2].kcode ); + } +} + +/* initialize time tables */ +static void init_timetables(const UINT8 *dttable) +{ + int i,d; + double rate; + + /* DeTune table */ + for (d = 0;d <= 3;d++){ + for (i = 0;i <= 31;i++){ + rate = ((double)dttable[d*32 + i]) * SIN_LEN * ym2612.OPN.ST.freqbase * (1<0.0) + o = 8*log(1.0/m)/log(2); /* convert to 'decibels' */ + else + o = 8*log(-1.0/m)/log(2); /* convert to 'decibels' */ + + o = o / (ENV_STEP/4); + + n = (int)(2.0*o); + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + + ym_sin_tab[ i ] = n; + //dprintf("FM.C: sin [%4i]= %4i", i, ym_sin_tab[i]); + } + + //dprintf("FM.C: ENV_QUIET= %08x", ENV_QUIET ); + + + for (x=0; x < TL_RES_LEN; x++) + { + m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0); + m = floor(m); + + /* we never reach (1<<16) here due to the (x+1) */ + /* result fits within 16 bits at maximum */ + + n = (int)m; /* 16 bits here */ + n >>= 4; /* 12 bits here */ + if (n&1) /* round to nearest */ + n = (n>>1)+1; + else + n = n>>1; + /* 11 bits here (rounded) */ + n <<= 2; /* 13 bits here (as in real chip) */ + ym_tl_tab2[ x ] = n; + + for (i=1; i < 13; i++) + { + ym_tl_tab2[ x + i*TL_RES_LEN ] = n >> i; + } + } + + for (x=0; x < 256; x++) + { + int sin = ym_sin_tab[ x ]; + + for (y=0; y < 2*13*TL_RES_LEN/8; y+=2) + { + p = (y<<2) + sin; + if (p >= 13*TL_RES_LEN) + ym_tl_tab[(y<<7) | x] = 0; + else ym_tl_tab[(y<<7) | x] = ym_tl_tab2[p]; + } + } + + + /* build LFO PM modulation table */ + for(i = 0; i < 8; i++) /* 8 PM depths */ + { + UINT8 fnum; + for (fnum=0; fnum<128; fnum++) /* 7 bits meaningful of F-NUMBER */ + { + UINT8 value; + UINT8 step; + UINT32 offset_depth = i; + UINT32 offset_fnum_bit; + UINT32 bit_tmp; + + for (step=0; step<8; step++) + { + value = 0; + for (bit_tmp=0; bit_tmp<7; bit_tmp++) /* 7 bits */ + { + if (fnum & (1< increment counter table */ + for(i = 0; i < 4096; i++) + { + /* freq table for octave 7 */ + /* OPN phase increment counter = 20bit */ + fn_table[i] = (UINT32)( (double)i * 32 * ym2612.OPN.ST.freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */ + } + + /* LFO freq. table */ + for(i = 0; i < 8; i++) + { + /* Amplitude modulation: 64 output levels (triangle waveform); 1 level lasts for one of "lfo_samples_per_step" samples */ + /* Phase modulation: one entry from lfo_pm_output lasts for one of 4 * "lfo_samples_per_step" samples */ + ym2612.OPN.lfo_freq[i] = (1.0 / lfo_samples_per_step[i]) * (1<= 0x100) c+=3; + + CH = &ym2612.CH[c]; + + SLOT = &(CH->SLOT[OPN_SLOT(r)]); + + switch( r & 0xf0 ) { + case 0x30: /* DET , MUL */ + set_det_mul(CH,SLOT,v); + break; + + case 0x40: /* TL */ + set_tl(SLOT,v); + break; + + case 0x50: /* KS, AR */ + set_ar_ksr(CH,SLOT,v); + break; + + case 0x60: /* bit7 = AM ENABLE, DR | depends on ksr */ + set_dr(SLOT,v); + if(v&0x80) CH->AMmasks |= 1<AMmasks &= ~(1<fn_h)&7))<<8) + v; + UINT8 blk = CH->fn_h>>3; + /* keyscale code */ + CH->kcode = (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + CH->fc = fn_table[fn*2]>>(7-blk); + + /* store fnum in clear form for LFO PM calculations */ + CH->block_fnum = (blk<<11) | fn; + + CH->SLOT[SLOT1].Incr=-1; + } + break; + case 1: /* 0xa4-0xa6 : FNUM2,BLK */ + CH->fn_h = v&0x3f; + ret = 0; + break; + case 2: /* 0xa8-0xaa : 3CH FNUM1 */ + if(r < 0x100) + { + UINT32 fn = (((UINT32)(ym2612.OPN.SL3.fn_h&7))<<8) + v; + UINT8 blk = ym2612.OPN.SL3.fn_h>>3; + /* keyscale code */ + ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; + /* phase increment counter */ + ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk); + ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn; + ym2612.CH[2].SLOT[SLOT1].Incr=-1; + } + break; + case 3: /* 0xac-0xae : 3CH FNUM2,BLK */ + if(r < 0x100) + ym2612.OPN.SL3.fn_h = v&0x3f; + ret = 0; + break; + default: + ret = 0; + break; + } + break; + + case 0xb0: + switch( OPN_SLOT(r) ){ + case 0: /* 0xb0-0xb2 : FB,ALGO */ + { + int feedback = (v>>3)&7; + CH->ALGO = v&7; + CH->FB = feedback ? feedback+6 : 0; + } + break; + case 1: /* 0xb4-0xb6 : L , R , AMS , PMS (YM2612/YM2610B/YM2610/YM2608) */ + { + int panshift = c<<1; + + /* b0-2 PMS */ + CH->pms = (v & 7) * 32; /* CH->pms = PM depth * 32 (index in lfo_pm_table) */ + + /* b4-5 AMS */ + CH->ams = lfo_ams_depth_shift[(v>>4) & 3]; + + /* PAN : b7 = L, b6 = R */ + ym2612.OPN.pan &= ~(3<> 6) << panshift; // ..LRLR + } + break; + default: + ret = 0; + break; + } + break; + default: + ret = 0; + break; + } + + return ret; +} + + +/*******************************************************************************/ +/* YM2612 local section */ +/*******************************************************************************/ + +/* Generate samples for YM2612 */ +int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty) +{ + int pan; + int active_chs = 0; + + // if !is_buf_empty, it means it has valid samples to mix with, else it may contain trash + if (is_buf_empty) memset32(buffer, 0, length<>2)) << 3; + if (ym2612.slot_mask & 0x0f0000) active_chs |= chan_render(buffer, length, 4, stereo|((pan&0x300)>>4)) << 4; + if (ym2612.slot_mask & 0xf00000) active_chs |= chan_render(buffer, length, 5, stereo|((pan&0xc00)>>6)|(ym2612.dacen<<2)) << 5; + chan_render_finish(); + + return active_chs; // 1 if buffer updated +} + + +/* initialize YM2612 emulator */ +void YM2612Init_(int clock, int rate) +{ + memset(&ym2612, 0, sizeof(ym2612)); + init_tables(); + + ym2612.OPN.ST.clock = clock; + ym2612.OPN.ST.rate = rate; + + OPNSetPres( 6*24 ); + + /* Extend handler */ + YM2612ResetChip_(); +} + + +/* reset */ +void YM2612ResetChip_(void) +{ + int i; + + memset(ym2612.REGS, 0, sizeof(ym2612.REGS)); + + set_timers( 0x30 ); /* mode 0 , timer reset */ + ym2612.REGS[0x27] = 0x30; + + ym2612.OPN.eg_timer = 0; + ym2612.OPN.eg_cnt = 0; + ym2612.OPN.ST.status = 0; + + reset_channels( &ym2612.CH[0] ); + for(i = 0xb6 ; i >= 0xb4 ; i-- ) + { + OPNWriteReg(i ,0xc0); + OPNWriteReg(i|0x100,0xc0); + ym2612.REGS[i ] = 0xc0; + ym2612.REGS[i|0x100] = 0xc0; + } + for(i = 0xb2 ; i >= 0x30 ; i-- ) + { + OPNWriteReg(i ,0); + OPNWriteReg(i|0x100,0); + } + for(i = 0x26 ; i >= 0x20 ; i-- ) OPNWriteReg(i,0); + /* DAC mode clear */ + ym2612.dacen = 0; + ym2612.addr_A1 = 0; +} + + +/* YM2612 write */ +/* a = address */ +/* v = value */ +/* returns 1 if sample affecting state changed */ +int YM2612Write_(unsigned int a, unsigned int v) +{ + int addr, ret=1; + + v &= 0xff; /* adjust to 8 bit bus */ + + switch( a&3){ + case 0: /* address port 0 */ + ym2612.OPN.ST.address = v; + ym2612.addr_A1 = 0; + ret=0; + break; + + case 1: /* data port 0 */ + if (ym2612.addr_A1 != 0) { + ret=0; + break; /* verified on real YM2608 */ + } + + addr = ym2612.OPN.ST.address; + + switch( addr & 0xf0 ) + { + case 0x20: /* 0x20-0x2f Mode */ + switch( addr ) + { + case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/YM2612) */ + if (v&0x08) /* LFO enabled ? */ + { + ym2612.OPN.lfo_inc = ym2612.OPN.lfo_freq[v&7]; + } + else + { + ym2612.OPN.lfo_inc = 0; + } + break; +#if 0 // handled elsewhere + case 0x24: { // timer A High 8 + int TAnew = (ym2612.OPN.ST.TA & 0x03)|(((int)v)<<2); + if(ym2612.OPN.ST.TA != TAnew) { + // we should reset ticker only if new value is written. Outrun requires this. + ym2612.OPN.ST.TA = TAnew; + ym2612.OPN.ST.TAC = (1024-TAnew)*18; + ym2612.OPN.ST.TAT = 0; + } + } + ret=0; + break; + case 0x25: { // timer A Low 2 + int TAnew = (ym2612.OPN.ST.TA & 0x3fc)|(v&3); + if(ym2612.OPN.ST.TA != TAnew) { + ym2612.OPN.ST.TA = TAnew; + ym2612.OPN.ST.TAC = (1024-TAnew)*18; + ym2612.OPN.ST.TAT = 0; + } + } + ret=0; + break; + case 0x26: // timer B + if(ym2612.OPN.ST.TB != v) { + ym2612.OPN.ST.TB = v; + ym2612.OPN.ST.TBC = (256-v)<<4; + ym2612.OPN.ST.TBC *= 18; + ym2612.OPN.ST.TBT = 0; + } + ret=0; + break; +#endif + case 0x27: /* mode, timer control */ + set_timers( v ); + ret=0; + break; + case 0x28: /* key on / off */ + { + UINT8 c; + + c = v & 0x03; + if( c == 3 ) { ret=0; break; } + if( v&0x04 ) c+=3; + if(v&0x10) FM_KEYON(c,SLOT1); else FM_KEYOFF(c,SLOT1); + if(v&0x20) FM_KEYON(c,SLOT2); else FM_KEYOFF(c,SLOT2); + if(v&0x40) FM_KEYON(c,SLOT3); else FM_KEYOFF(c,SLOT3); + if(v&0x80) FM_KEYON(c,SLOT4); else FM_KEYOFF(c,SLOT4); + break; + } + case 0x2a: /* DAC data (YM2612) */ + ym2612.dacout = ((int)v - 0x80) << 6; /* level unknown (notaz: 8 seems to be too much) */ + ret=0; + break; + case 0x2b: /* DAC Sel (YM2612) */ + /* b7 = dac enable */ + ym2612.dacen = v & 0x80; + ret=0; + break; + default: + break; + } + break; + default: /* 0x30-0xff OPN section */ + /* write register */ + ret = OPNWriteReg(addr,v); + } + break; + + case 2: /* address port 1 */ + ym2612.OPN.ST.address = v; + ym2612.addr_A1 = 1; + ret=0; + break; + + case 3: /* data port 1 */ + if (ym2612.addr_A1 != 1) { + ret=0; + break; /* verified on real YM2608 */ + } + + addr = ym2612.OPN.ST.address | 0x100; + + ret = OPNWriteReg(addr, v); + break; + } + + return ret; +} + +#if 0 +UINT8 YM2612Read_(void) +{ + return ym2612.OPN.ST.status; +} + +int YM2612PicoTick_(int n) +{ + int ret = 0; + + // timer A + if(ym2612.OPN.ST.mode & 0x01 && (ym2612.OPN.ST.TAT+=64*n) >= ym2612.OPN.ST.TAC) { + ym2612.OPN.ST.TAT -= ym2612.OPN.ST.TAC; + if(ym2612.OPN.ST.mode & 0x04) ym2612.OPN.ST.status |= 1; + // CSM mode total level latch and auto key on + if(ym2612.OPN.ST.mode & 0x80) { + CSMKeyControll( &(ym2612.CH[2]) ); // Vectorman2, etc. + ret = 1; + } + } + + // timer B + if(ym2612.OPN.ST.mode & 0x02 && (ym2612.OPN.ST.TBT+=64*n) >= ym2612.OPN.ST.TBC) { + ym2612.OPN.ST.TBT -= ym2612.OPN.ST.TBC; + if(ym2612.OPN.ST.mode & 0x08) ym2612.OPN.ST.status |= 2; + } + + return ret; +} +#endif + +void YM2612PicoStateLoad_(void) +{ + reset_channels( &ym2612.CH[0] ); + ym2612.slot_mask = 0xffffff; +} + +/* rather stupid design because I wanted to fit in unused register "space" */ +typedef struct +{ + UINT32 state_phase; + INT16 volume; +} ym_save_addon_slot; + +typedef struct +{ + UINT32 magic; + UINT8 address; + UINT8 status; + UINT8 addr_A1; + UINT8 unused; + int TAT; + int TBT; + UINT32 eg_cnt; // 10 + UINT32 eg_timer; + UINT32 lfo_cnt; + UINT16 lfo_ampm; + UINT16 unused2; + UINT32 keyon_field; // 20 + UINT32 kcode_fc_sl3_3; + UINT32 reserved[2]; +} ym_save_addon; + +typedef struct +{ + UINT16 block_fnum[6]; + UINT16 block_fnum_sl3[3]; + UINT16 reserved[7]; +} ym_save_addon2; + + +void YM2612PicoStateSave2(int tat, int tbt) +{ + ym_save_addon_slot ss; + ym_save_addon2 sa2; + ym_save_addon sa; + unsigned char *ptr; + int c, s; + + memset(&sa, 0, sizeof(sa)); + memset(&sa2, 0, sizeof(sa2)); + + // chans 1,2,3 + ptr = &ym2612.REGS[0x0b8]; + for (c = 0; c < 3; c++) + { + for (s = 0; s < 4; s++) { + ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3); + ss.volume = ym2612.CH[c].SLOT[s].volume; + if (ym2612.CH[c].SLOT[s].key) + sa.keyon_field |= 1 << (c*4 + s); + memcpy(ptr, &ss, 6); + ptr += 6; + } + sa2.block_fnum[c] = ym2612.CH[c].block_fnum; + } + // chans 4,5,6 + ptr = &ym2612.REGS[0x1b8]; + for (; c < 6; c++) + { + for (s = 0; s < 4; s++) { + ss.state_phase = (ym2612.CH[c].SLOT[s].state << 29) | (ym2612.CH[c].SLOT[s].phase >> 3); + ss.volume = ym2612.CH[c].SLOT[s].volume; + if (ym2612.CH[c].SLOT[s].key) + sa.keyon_field |= 1 << (c*4 + s); + memcpy(ptr, &ss, 6); + ptr += 6; + } + sa2.block_fnum[c] = ym2612.CH[c].block_fnum; + } + for (c = 0; c < 3; c++) + { + sa2.block_fnum_sl3[c] = ym2612.OPN.SL3.block_fnum[c]; + } + + memcpy(&ym2612.REGS[0], &sa2, sizeof(sa2)); // 0x20 max + + // other things + ptr = &ym2612.REGS[0x100]; + sa.magic = 0x41534d59; // 'YMSA' + sa.address = ym2612.OPN.ST.address; + sa.status = ym2612.OPN.ST.status; + sa.addr_A1 = ym2612.addr_A1; + sa.TAT = tat; + sa.TBT = tbt; + sa.eg_cnt = ym2612.OPN.eg_cnt; + sa.eg_timer = ym2612.OPN.eg_timer; + sa.lfo_cnt = ym2612.OPN.lfo_cnt; + sa.lfo_ampm = g_lfo_ampm; + memcpy(ptr, &sa, sizeof(sa)); // 0x30 max +} + +int YM2612PicoStateLoad2(int *tat, int *tbt) +{ + ym_save_addon_slot ss; + ym_save_addon2 sa2; + ym_save_addon sa; + unsigned char *ptr; + UINT32 fn; + UINT8 blk; + int c, s; + + ptr = &ym2612.REGS[0x100]; + memcpy(&sa, ptr, sizeof(sa)); // 0x30 max + if (sa.magic != 0x41534d59) return -1; + + ptr = &ym2612.REGS[0]; + memcpy(&sa2, ptr, sizeof(sa2)); + + ym2612.OPN.ST.address = sa.address; + ym2612.OPN.ST.status = sa.status; + ym2612.addr_A1 = sa.addr_A1; + ym2612.OPN.eg_cnt = sa.eg_cnt; + ym2612.OPN.eg_timer = sa.eg_timer; + ym2612.OPN.lfo_cnt = sa.lfo_cnt; + g_lfo_ampm = sa.lfo_ampm; + if (tat != NULL) *tat = sa.TAT; + if (tbt != NULL) *tbt = sa.TBT; + + // chans 1,2,3 + ptr = &ym2612.REGS[0x0b8]; + for (c = 0; c < 3; c++) + { + for (s = 0; s < 4; s++) { + memcpy(&ss, ptr, 6); + ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29; + ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3; + ym2612.CH[c].SLOT[s].volume = ss.volume; + ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0; + ym2612.CH[c].SLOT[s].ksr = (UINT8)-1; + ptr += 6; + } + ym2612.CH[c].SLOT[SLOT1].Incr=-1; + ym2612.CH[c].block_fnum = sa2.block_fnum[c]; + fn = ym2612.CH[c].block_fnum & 0x7ff; + blk = ym2612.CH[c].block_fnum >> 11; + ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7]; + ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk); + } + // chans 4,5,6 + ptr = &ym2612.REGS[0x1b8]; + for (; c < 6; c++) + { + for (s = 0; s < 4; s++) { + memcpy(&ss, ptr, 6); + ym2612.CH[c].SLOT[s].state = ss.state_phase >> 29; + ym2612.CH[c].SLOT[s].phase = ss.state_phase << 3; + ym2612.CH[c].SLOT[s].volume = ss.volume; + ym2612.CH[c].SLOT[s].key = (sa.keyon_field & (1 << (c*4 + s))) ? 1 : 0; + ym2612.CH[c].SLOT[s].ksr = (UINT8)-1; + ptr += 6; + } + ym2612.CH[c].SLOT[SLOT1].Incr=-1; + ym2612.CH[c].block_fnum = sa2.block_fnum[c]; + fn = ym2612.CH[c].block_fnum & 0x7ff; + blk = ym2612.CH[c].block_fnum >> 11; + ym2612.CH[c].kcode= (blk<<2) | opn_fktable[fn >> 7]; + ym2612.CH[c].fc = fn_table[fn*2]>>(7-blk); + } + for (c = 0; c < 3; c++) + { + ym2612.OPN.SL3.block_fnum[c] = sa2.block_fnum_sl3[c]; + fn = ym2612.OPN.SL3.block_fnum[c] & 0x7ff; + blk = ym2612.OPN.SL3.block_fnum[c] >> 11; + ym2612.OPN.SL3.kcode[c]= (blk<<2) | opn_fktable[fn >> 7]; + ym2612.OPN.SL3.fc[c] = fn_table[fn*2]>>(7-blk); + } + + return 0; +} + +void *YM2612GetRegs(void) +{ + return ym2612.REGS; +} + diff --git a/waterbox/picodrive/pico/sound/ym2612.h b/waterbox/picodrive/pico/sound/ym2612.h new file mode 100644 index 0000000000..f5e98a0578 --- /dev/null +++ b/waterbox/picodrive/pico/sound/ym2612.h @@ -0,0 +1,192 @@ +/* + header file for software emulation for FM sound generator + +*/ +#ifndef _H_FM_FM_ +#define _H_FM_FM_ + +/* compiler dependence */ +#ifndef UINT8 +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +#endif +#ifndef INT8 +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif + +#if 1 +/* struct describing a single operator (SLOT) */ +typedef struct +{ + INT32 *DT; /* #0x00 detune :dt_tab[DT] */ + UINT8 ar; /* #0x04 attack rate */ + UINT8 d1r; /* #0x05 decay rate */ + UINT8 d2r; /* #0x06 sustain rate */ + UINT8 rr; /* #0x07 release rate */ + UINT32 mul; /* #0x08 multiple :ML_TABLE[ML] */ + + /* Phase Generator */ + UINT32 phase; /* #0x0c phase counter | need_save */ + UINT32 Incr; /* #0x10 phase step */ + + UINT8 KSR; /* #0x14 key scale rate :3-KSR */ + UINT8 ksr; /* #0x15 key scale rate :kcode>>(3-KSR) */ + + UINT8 key; /* #0x16 0=last key was KEY OFF, 1=KEY ON */ + + /* Envelope Generator */ + UINT8 state; /* #0x17 phase type: EG_OFF=0, EG_REL, EG_SUS, EG_DEC, EG_ATT | need_save */ + UINT16 tl; /* #0x18 total level: TL << 3 */ + INT16 volume; /* #0x1a envelope counter | need_save */ + UINT32 sl; /* #0x1c sustain level:sl_table[SL] */ + + UINT32 eg_pack_ar; /* #0x20 (attack state) */ + UINT32 eg_pack_d1r; /* #0x24 (decay state) */ + UINT32 eg_pack_d2r; /* #0x28 (sustain state) */ + UINT32 eg_pack_rr; /* #0x2c (release state) */ +} FM_SLOT; + + +typedef struct +{ + FM_SLOT SLOT[4]; /* four SLOTs (operators) */ + + UINT8 ALGO; /* +00 algorithm */ + UINT8 FB; /* feedback shift */ + UINT8 pad[2]; + INT32 op1_out; /* op1 output for feedback */ + + INT32 mem_value; /* +08 delayed sample (MEM) value */ + + INT32 pms; /* channel PMS */ + UINT8 ams; /* channel AMS */ + + UINT8 kcode; /* +11 key code: */ + UINT8 fn_h; /* freq latch */ + UINT8 pad2; + UINT32 fc; /* fnum,blk:adjusted to sample rate */ + UINT32 block_fnum; /* current blk/fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ + + /* LFO */ + UINT8 AMmasks; /* AM enable flag */ + UINT8 pad3[3]; +} FM_CH; + +typedef struct +{ + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* 08 frequency base */ + UINT8 address; /* 10 address register | need_save */ + UINT8 status; /* 11 status flag | need_save */ + UINT8 mode; /* mode CSM / 3SLOT */ + UINT8 pad; + int TA; /* timer a */ + int TAC; /* timer a maxval */ + int TAT; /* timer a ticker | need_save */ + UINT8 TB; /* timer b */ + UINT8 pad2[3]; + int TBC; /* timer b maxval */ + int TBT; /* timer b ticker | need_save */ + /* local time tables */ + INT32 dt_tab[8][32];/* DeTune table */ +} FM_ST; + +/***********************************************************/ +/* OPN unit */ +/***********************************************************/ + +/* OPN 3slot struct */ +typedef struct +{ + UINT32 fc[3]; /* fnum3,blk3: calculated */ + UINT8 fn_h; /* freq3 latch */ + UINT8 kcode[3]; /* key code */ + UINT32 block_fnum[3]; /* current fnum value for this slot (can be different betweeen slots of one channel in 3slot mode) */ +} FM_3SLOT; + +/* OPN/A/B common state */ +typedef struct +{ + FM_ST ST; /* general state */ + FM_3SLOT SL3; /* 3 slot mode state */ + UINT32 pan; /* fm channels output mask (bit 1 = enable) */ + + UINT32 eg_cnt; /* global envelope generator counter | need_save */ + UINT32 eg_timer; /* global envelope generator counter works at frequency = chipclock/64/3 | need_save */ + UINT32 eg_timer_add; /* step of eg_timer */ + + /* LFO */ + UINT32 lfo_cnt; /* need_save */ + UINT32 lfo_inc; + + UINT32 lfo_freq[8]; /* LFO FREQ table */ +} FM_OPN; + +/* here's the virtual YM2612 */ +typedef struct +{ + UINT8 REGS[0x200]; /* registers (for save states) */ + INT32 addr_A1; /* address line A1 | need_save */ + + FM_CH CH[6]; /* channel state */ + + /* dac output (YM2612) */ + int dacen; + INT32 dacout; + + FM_OPN OPN; /* OPN state */ + + UINT32 slot_mask; /* active slot mask (performance hack) */ +} YM2612; +#endif + +#ifndef EXTERNAL_YM2612 +extern YM2612 ym2612; +#endif + +void YM2612Init_(int baseclock, int rate); +void YM2612ResetChip_(void); +int YM2612UpdateOne_(int *buffer, int length, int stereo, int is_buf_empty); + +int YM2612Write_(unsigned int a, unsigned int v); +//unsigned char YM2612Read_(void); + +int YM2612PicoTick_(int n); +void YM2612PicoStateLoad_(void); + +void *YM2612GetRegs(void); +void YM2612PicoStateSave2(int tat, int tbt); +int YM2612PicoStateLoad2(int *tat, int *tbt); + +#ifndef __GP2X__ +#define YM2612Init YM2612Init_ +#define YM2612ResetChip YM2612ResetChip_ +#define YM2612UpdateOne YM2612UpdateOne_ +#define YM2612PicoStateLoad YM2612PicoStateLoad_ +#else +/* GP2X specific */ +#include "../../platform/gp2x/940ctl.h" +extern int PicoOpt; +#define YM2612Init(baseclock,rate) { \ + if (PicoOpt&0x200) YM2612Init_940(baseclock, rate); \ + else YM2612Init_(baseclock, rate); \ +} +#define YM2612ResetChip() { \ + if (PicoOpt&0x200) YM2612ResetChip_940(); \ + else YM2612ResetChip_(); \ +} +#define YM2612UpdateOne(buffer,length,stereo,is_buf_empty) \ + (PicoOpt&0x200) ? YM2612UpdateOne_940(buffer, length, stereo, is_buf_empty) : \ + YM2612UpdateOne_(buffer, length, stereo, is_buf_empty); +#define YM2612PicoStateLoad() { \ + if (PicoOpt&0x200) YM2612PicoStateLoad_940(); \ + else YM2612PicoStateLoad_(); \ +} +#endif /* __GP2X__ */ + + +#endif /* _H_FM_FM_ */ diff --git a/waterbox/picodrive/pico/videoport.c b/waterbox/picodrive/pico/videoport.c new file mode 100644 index 0000000000..6c876aeaad --- /dev/null +++ b/waterbox/picodrive/pico/videoport.c @@ -0,0 +1,549 @@ +/* + * PicoDrive + * (c) Copyright Dave, 2004 + * (C) notaz, 2006-2009 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include "pico_int.h" + +int line_base_cycles; +extern const unsigned char hcounts_32[]; +extern const unsigned char hcounts_40[]; + +#ifndef UTYPES_DEFINED +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +#define UTYPES_DEFINED +#endif + +int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp) = NULL; + +static __inline void AutoIncrement(void) +{ + Pico.video.addr=(unsigned short)(Pico.video.addr+Pico.video.reg[0xf]); +} + +static void VideoWrite(u16 d) +{ + unsigned int a=Pico.video.addr; + + switch (Pico.video.type) + { + case 1: if(a&1) d=(u16)((d<<8)|(d>>8)); // If address is odd, bytes are swapped (which game needs this?) + Pico.vram [(a>>1)&0x7fff]=d; + if (a - ((unsigned)(Pico.video.reg[5]&0x7f) << 9) < 0x400) + rendstatus |= PDRAW_DIRTY_SPRITES; + break; + case 3: Pico.m.dirtyPal = 1; + Pico.cram [(a>>1)&0x003f]=d; break; // wraps (Desert Strike) + case 5: Pico.vsram[(a>>1)&0x003f]=d; break; + //default:elprintf(EL_ANOMALY, "VDP write %04x with bad type %i", d, Pico.video.type); break; + } + + AutoIncrement(); +} + +static unsigned int VideoRead(void) +{ + unsigned int a=0,d=0; + + a=Pico.video.addr; a>>=1; + + switch (Pico.video.type) + { + case 0: d=Pico.vram [a&0x7fff]; break; + case 8: d=Pico.cram [a&0x003f]; break; + case 4: d=Pico.vsram[a&0x003f]; break; + default:elprintf(EL_ANOMALY, "VDP read with bad type %i", Pico.video.type); break; + } + + AutoIncrement(); + return d; +} + +static int GetDmaLength(void) +{ + struct PicoVideo *pvid=&Pico.video; + int len=0; + // 16-bit words to transfer: + len =pvid->reg[0x13]; + len|=pvid->reg[0x14]<<8; + // Charles MacDonald: + if(!len) len = 0xffff; + return len; +} + +static void DmaSlow(int len) +{ + u16 *pd=0, *pdend, *r; + unsigned int a=Pico.video.addr, a2, d; + unsigned char inc=Pico.video.reg[0xf]; + unsigned int source; + + source =Pico.video.reg[0x15]<<1; + source|=Pico.video.reg[0x16]<<9; + source|=Pico.video.reg[0x17]<<17; + + elprintf(EL_VDPDMA, "DmaSlow[%i] %06x->%04x len %i inc=%i blank %i [%i] @ %06x", + Pico.video.type, source, a, len, inc, (Pico.video.status&8)||!(Pico.video.reg[1]&0x40), + SekCyclesDone(), SekPc); + + Pico.m.dma_xfers += len; + SekCyclesBurnRun(CheckDMA()); + + if ((source&0xe00000)==0xe00000) { // Ram + pd=(u16 *)(Pico.ram+(source&0xfffe)); + pdend=(u16 *)(Pico.ram+0x10000); + } + else if (PicoAHW & PAHW_MCD) + { + elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", Pico_mcd->s68k_regs[3]); + if(source<0x20000) { // Bios area + pd=(u16 *)(Pico_mcd->bios+(source&~1)); + pdend=(u16 *)(Pico_mcd->bios+0x20000); + } else if ((source&0xfc0000)==0x200000) { // Word Ram + source -= 2; + if (!(Pico_mcd->s68k_regs[3]&4)) { // 2M mode + pd=(u16 *)(Pico_mcd->word_ram2M+(source&0x3fffe)); + pdend=(u16 *)(Pico_mcd->word_ram2M+0x40000); + } else { + if (source < 0x220000) { // 1M mode + int bank = Pico_mcd->s68k_regs[3]&1; + pd=(u16 *)(Pico_mcd->word_ram1M[bank]+(source&0x1fffe)); + pdend=(u16 *)(Pico_mcd->word_ram1M[bank]+0x20000); + } else { + DmaSlowCell(source, a, len, inc); + return; + } + } + } else if ((source&0xfe0000)==0x020000) { // Prg Ram + u8 *prg_ram = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3]>>6]; + pd=(u16 *)(prg_ram+(source&0x1fffe)); + pdend=(u16 *)(prg_ram+0x20000); + } else { + elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: FIXME: unsupported src", Pico.video.type, source, a); + return; + } + } + else + { + // if we have DmaHook, let it handle ROM because of possible DMA delay + if (PicoDmaHook && PicoDmaHook(source, len, &pd, &pdend)); + else if (source%04x: invalid src", Pico.video.type, source, a); + return; + } + } + + // overflow protection, might break something.. + if (len > pdend - pd) { + len = pdend - pd; + elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow overflow"); + } + + switch (Pico.video.type) + { + case 1: // vram + r = Pico.vram; + if (inc == 2 && !(a&1) && a+len*2 < 0x10000) + { + // most used DMA mode + memcpy16(r + (a>>1), pd, len); + a += len*2; + } + else + { + for(; len; len--) + { + d=*pd++; + if(a&1) d=(d<<8)|(d>>8); + r[a>>1] = (u16)d; // will drop the upper bits + // AutoIncrement + a=(u16)(a+inc); + // didn't src overlap? + //if(pd >= pdend) pd-=0x8000; // should be good for RAM, bad for ROM + } + } + rendstatus |= PDRAW_DIRTY_SPRITES; + break; + + case 3: // cram + Pico.m.dirtyPal = 1; + r = Pico.cram; + for(a2=a&0x7f; len; len--) + { + r[a2>>1] = (u16)*pd++; // bit 0 is ignored + // AutoIncrement + a2+=inc; + // didn't src overlap? + //if(pd >= pdend) pd-=0x8000; + // good dest? + if(a2 >= 0x80) break; // Todds Adventures in Slime World / Andre Agassi tennis + } + a=(a&0xff00)|a2; + break; + + case 5: // vsram[a&0x003f]=d; + r = Pico.vsram; + for(a2=a&0x7f; len; len--) + { + r[a2>>1] = (u16)*pd++; + // AutoIncrement + a2+=inc; + // didn't src overlap? + //if(pd >= pdend) pd-=0x8000; + // good dest? + if(a2 >= 0x80) break; + } + a=(a&0xff00)|a2; + break; + + default: + if (Pico.video.type != 0 || (EL_LOGMASK & EL_VDPDMA)) + elprintf(EL_VDPDMA|EL_ANOMALY, "DMA with bad type %i", Pico.video.type); + break; + } + // remember addr + Pico.video.addr=(u16)a; +} + +static void DmaCopy(int len) +{ + u16 a=Pico.video.addr; + unsigned char *vr = (unsigned char *) Pico.vram; + unsigned char *vrs; + unsigned char inc=Pico.video.reg[0xf]; + int source; + elprintf(EL_VDPDMA, "DmaCopy len %i [%i]", len, SekCyclesDone()); + + Pico.m.dma_xfers += len; + Pico.video.status |= 2; // dma busy + + source =Pico.video.reg[0x15]; + source|=Pico.video.reg[0x16]<<8; + vrs=vr+source; + + if (source+len > 0x10000) len=0x10000-source; // clip?? + + for (; len; len--) + { + vr[a] = *vrs++; + // AutoIncrement + a=(u16)(a+inc); + } + // remember addr + Pico.video.addr=a; + rendstatus |= PDRAW_DIRTY_SPRITES; +} + +// check: Contra, Megaman +// note: this is still inaccurate +static void DmaFill(int data) +{ + int len; + unsigned short a=Pico.video.addr; + unsigned char *vr=(unsigned char *) Pico.vram; + unsigned char high = (unsigned char) (data >> 8); + unsigned char inc=Pico.video.reg[0xf]; + + len=GetDmaLength(); + elprintf(EL_VDPDMA, "DmaFill len %i inc %i [%i]", len, inc, SekCyclesDone()); + + Pico.m.dma_xfers += len; + Pico.video.status |= 2; // dma busy + + // from Charles MacDonald's genvdp.txt: + // Write lower byte to address specified + vr[a] = (unsigned char) data; + a=(u16)(a+inc); + + if (!inc) len=1; + + for (; len; len--) { + // Write upper byte to adjacent address + // (here we are byteswapped, so address is already 'adjacent') + vr[a] = high; + + // Increment address register + a=(u16)(a+inc); + } + // remember addr + Pico.video.addr=a; + // update length + Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze) + + rendstatus |= PDRAW_DIRTY_SPRITES; +} + +static void CommandDma(void) +{ + struct PicoVideo *pvid=&Pico.video; + int len=0,method=0; + + if ((pvid->reg[1]&0x10)==0) return; // DMA not enabled + + len=GetDmaLength(); + + method=pvid->reg[0x17]>>6; + if (method< 2) DmaSlow(len); // 68000 to VDP + if (method==3) DmaCopy(len); // VRAM Copy +} + +static void CommandChange(void) +{ + struct PicoVideo *pvid=&Pico.video; + unsigned int cmd=0,addr=0; + + cmd=pvid->command; + + // Get type of transfer 0xc0000030 (v/c/vsram read/write) + pvid->type=(unsigned char)(((cmd>>2)&0xc)|(cmd>>30)); + + // Get address 0x3fff0003 + addr =(cmd>>16)&0x3fff; + addr|=(cmd<<14)&0xc000; + pvid->addr=(unsigned short)addr; + + // Check for dma: + if (cmd&0x80) CommandDma(); +} + +static void DrawSync(int blank_on) +{ + if (Pico.m.scanline < 224 && !(PicoOpt & POPT_ALT_RENDERER) && + !PicoSkipFrame && DrawScanline <= Pico.m.scanline) { + //elprintf(EL_ANOMALY, "sync"); + PicoDrawSync(Pico.m.scanline, blank_on); + } +} + +PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d) +{ + struct PicoVideo *pvid=&Pico.video; + + //if (Pico.m.scanline < 224) + // elprintf(EL_STATUS, "PicoVideoWrite [%06x] %04x", a, d); + a&=0x1c; + + if (a==0x00) // Data port 0 or 2 + { + // try avoiding the sync.. + if (Pico.m.scanline < 224 && (pvid->reg[1]&0x40) && + !(!pvid->pending && + ((pvid->command & 0xc00000f0) == 0x40000010 && Pico.vsram[pvid->addr>>1] == d)) + ) + DrawSync(0); + + if (pvid->pending) { + CommandChange(); + pvid->pending=0; + } + + // If a DMA fill has been set up, do it + if ((pvid->command&0x80) && (pvid->reg[1]&0x10) && (pvid->reg[0x17]>>6)==2) + { + DmaFill(d); + } + else + { + // preliminary FIFO emulation for Chaos Engine, The (E) + if (!(pvid->status&8) && (pvid->reg[1]&0x40) && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display? + { + pvid->status&=~0x200; // FIFO no longer empty + pvid->lwrite_cnt++; + if (pvid->lwrite_cnt >= 4) pvid->status|=0x100; // FIFO full + if (pvid->lwrite_cnt > 4) { + SekCyclesBurnRun(32); // penalty // 488/12-8 + } + elprintf(EL_ASVDP, "VDP data write: %04x [%06x] {%i} #%i @ %06x", d, Pico.video.addr, + Pico.video.type, pvid->lwrite_cnt, SekPc); + } + VideoWrite(d); + } + return; + } + + if (a==0x04) // Control (command) port 4 or 6 + { + if (pvid->pending) + { + if (d & 0x80) DrawSync(0); // only need sync for DMA + // Low word of command: + pvid->command&=0xffff0000; + pvid->command|=d; + pvid->pending=0; + CommandChange(); + } + else + { + if ((d&0xc000)==0x8000) + { + // Register write: + int num=(d>>8)&0x1f; + int dold=pvid->reg[num]; + int blank_on = 0; + pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II) + if (num > 0x0a && !(pvid->reg[1]&4)) { + elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc); + return; + } + + if (num == 1 && !(d&0x40) && SekCyclesDone() - line_base_cycles <= 488-390) + blank_on = 1; + DrawSync(blank_on); + pvid->reg[num]=(unsigned char)d; + switch (num) + { + case 0x00: + elprintf(EL_INTSW, "hint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x10)>>4, + (d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc); + goto update_irq; + case 0x01: + elprintf(EL_INTSW, "vint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x20)>>5, + (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc); + goto update_irq; + case 0x05: + //elprintf(EL_STATUS, "spritep moved to %04x", (unsigned)(Pico.video.reg[5]&0x7f) << 9); + if (d^dold) rendstatus |= PDRAW_SPRITES_MOVED; + break; + case 0x0c: + // renderers should update their palettes if sh/hi mode is changed + if ((d^dold)&8) Pico.m.dirtyPal = 2; + break; + } + return; + +update_irq: +#ifndef EMU_CORE_DEBUG + // update IRQ level + if (!SekShouldInterrupt()) // hack + { + int lines, pints, irq=0; + lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10); + pints = (pvid->pending_ints&lines); + if (pints & 0x20) irq = 6; + else if (pints & 0x10) irq = 4; + SekInterrupt(irq); // update line + + if (irq) SekEndRun(24); // make it delayed + } +#endif + } + else + { + // High word of command: + pvid->command&=0x0000ffff; + pvid->command|=d<<16; + pvid->pending=1; + } + } + } +} + +PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a) +{ + a&=0x1c; + + if (a==0x04) // control port + { + struct PicoVideo *pv=&Pico.video; + unsigned int d; + d=pv->status; + //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) + if (SekCyclesDone() - line_base_cycles >= 488-88) + d|=0x0004; // H-Blank (Sonic3 vs) + + d |= ((pv->reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled + d |= (pv->pending_ints&0x20)<<2; // V-int pending? + if (d&0x100) pv->status&=~0x100; // FIFO no longer full + + pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald) + + elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc); + return d; + } + + // H-counter info (based on Generator): + // frame: + // | <- hblank? -> | + // start <416> hint <36> hdisplay <38> end // CPU cycles + // |---------...---------|------------|-------------| + // 0 B6 E4 FF // 40 cells + // 0 93 E8 FF // 32 cells + + // Gens (?) v-render + // start hint hdisplay <404> | + // |---------------------|--------------------------| + // E4 (hc[0x43]==0) 07 B1 // 40 + // E8 (hc[0x45]==0) 05 91 // 32 + + // check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune + if ((a&0x1c)==0x08) + { + unsigned int d; + + d = (SekCyclesDone() - line_base_cycles) & 0x1ff; // FIXME + if (Pico.video.reg[12]&1) + d = hcounts_40[d]; + else d = hcounts_32[d]; + + elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc); + return d | (Pico.video.v_counter << 8); + } + + if (a==0x00) // data port + { + return VideoRead(); + } + + return 0; +} + +unsigned int PicoVideoRead8(unsigned int a) +{ + unsigned int d; + a&=0x1d; + + switch (a) + { + case 0: return VideoRead() >> 8; + case 1: return VideoRead() & 0xff; + case 4: // control port/status reg + d = Pico.video.status >> 8; + if (d&1) Pico.video.status&=~0x100; // FIFO no longer full + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc); + return d; + case 5: + d = Pico.video.status & 0xff; + //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast) + d |= ((Pico.video.reg[1]&0x40)^0x40) >> 3; // set V-Blank if display is disabled + d |= (Pico.video.pending_ints&0x20)<<2; // V-int pending? + if (SekCyclesDone() - line_base_cycles >= 488-88) d |= 4; // H-Blank + Pico.video.pending = 0; + elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc); + return d; + case 8: // hv counter + elprintf(EL_HVCNT, "vcounter: %02x (%i) @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc); + return Pico.video.v_counter; + case 9: + d = (SekCyclesDone() - line_base_cycles) & 0x1ff; // FIXME + if (Pico.video.reg[12]&1) + d = hcounts_40[d]; + else d = hcounts_32[d]; + elprintf(EL_HVCNT, "hcounter: %02x (%i) @ %06x", d, SekCyclesDone(), SekPc); + return d; + } + + return 0; +} + +// vim:shiftwidth=2:ts=2:expandtab diff --git a/waterbox/picodrive/pico/z80if.c b/waterbox/picodrive/pico/z80if.c new file mode 100644 index 0000000000..8db4aa5c31 --- /dev/null +++ b/waterbox/picodrive/pico/z80if.c @@ -0,0 +1,288 @@ +/* + * PicoDrive + * (C) notaz, 2007-2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ + +#include +#include "pico_int.h" +#include "memory.h" + +uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT]; +uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT]; + +#ifdef _USE_DRZ80 +struct DrZ80 drZ80; + +static u32 drz80_sp_base; + +static void drz80_load_pcsp(u32 pc, u32 sp) +{ + drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT]; + if (drZ80.Z80PC_BASE & (1<<31)) { + elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad PC: %04x", pc); + drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0]; + } else { + drZ80.Z80PC_BASE <<= 1; + drZ80.Z80PC = drZ80.Z80PC_BASE + pc; + } + drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT]; + if (drZ80.Z80SP_BASE & (1<<31)) { + elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad SP: %04x", sp); + drZ80.Z80SP_BASE = z80_read_map[0]; + drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT); + } else { + drZ80.Z80SP_BASE <<= 1; + drZ80.Z80SP = drZ80.Z80SP_BASE + sp; + } +} + +// called only if internal xmap rebase fails +static unsigned int dz80_rebase_pc(unsigned short pc) +{ + elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_pc: fail on %04x", pc); + drZ80.Z80PC_BASE = z80_read_map[0] << 1; + return drZ80.Z80PC_BASE; +} + +static unsigned int dz80_rebase_sp(unsigned short sp) +{ + elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_sp: fail on %04x", sp); + drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1; + return drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT) - 0x100; +} +#endif + + +void z80_init(void) +{ +#ifdef _USE_DRZ80 + memset(&drZ80, 0, sizeof(drZ80)); + drZ80.z80_rebasePC = dz80_rebase_pc; + drZ80.z80_rebaseSP = dz80_rebase_sp; + drZ80.z80_read8 = (void *)z80_read_map; + drZ80.z80_read16 = NULL; + drZ80.z80_write8 = (void *)z80_write_map; + drZ80.z80_write16 = NULL; + drZ80.z80_irq_callback = NULL; +#endif +#ifdef _USE_CZ80 + memset(&CZ80, 0, sizeof(CZ80)); + Cz80_Init(&CZ80); + Cz80_Set_ReadB(&CZ80, NULL); // unused (hacked in) + Cz80_Set_WriteB(&CZ80, NULL); +#endif +} + +void z80_reset(void) +{ +#ifdef _USE_DRZ80 + drZ80.Z80I = 0; + drZ80.Z80IM = 0; + drZ80.Z80IF = 0; + drZ80.z80irqvector = 0xff0000; // RST 38h + drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1; + // others not changed, undefined on cold boot +/* + drZ80.Z80F = (1<<2); // set ZFlag + drZ80.Z80F2 = (1<<2); // set ZFlag + drZ80.Z80IX = 0xFFFF << 16; + drZ80.Z80IY = 0xFFFF << 16; +*/ + // drZ80 is locked in single bank + drz80_sp_base = (PicoAHW & PAHW_SMS) ? 0xc000 : 0x0000; + drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1; + if (PicoAHW & PAHW_SMS) + drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS + // XXX: since we use direct SP pointer, it might make sense to force it to RAM, + // but we'll rely on built-in stack protection for now +#endif +#ifdef _USE_CZ80 + Cz80_Reset(&CZ80); + if (PicoAHW & PAHW_SMS) + Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0); +#endif +} + +/* save state stuff */ +static int z80_unpack_legacy(const void *data) +{ +#if defined(_USE_DRZ80) + if (*(int *)data == 0x015A7244) { // "DrZ" v1 save? + u32 pc, sp; + memcpy(&drZ80, data+4, 0x54); + pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff; + sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff; + // update bases + drz80_load_pcsp(pc, sp); + return 0; + } +#elif defined(_USE_CZ80) + if (*(int *)data == 0x00007a43) { // "Cz" save? + memcpy(&CZ80, data+8, offsetof(cz80_struc, BasePC)); + Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4)); + return 0; + } +#endif + return -1; +} + +struct z80sr_main { + u8 a, f; + u8 b, c; + u8 d, e; + u8 h, l; +}; + +struct z80_state { + char magic[4]; + // regs + struct z80sr_main m; // main regs + struct z80sr_main a; // alt (') regs + u8 i, r; + u16 ix, iy; + u16 sp; + u16 pc; + // other + u8 halted; + u8 iff1, iff2; + u8 im; // irq mode + u8 irq_pending; // irq line level, 1 if active + u8 irq_vector[3]; // up to 3 byte vector for irq mode0 handling + u8 reserved[8]; +}; + +void z80_pack(void *data) +{ + struct z80_state *s = data; + memset(data, 0, Z80_STATE_SIZE); + strcpy(s->magic, "Z80"); +#if defined(_USE_DRZ80) + #define DRR8(n) (drZ80.Z80##n >> 24) + #define DRR16(n) (drZ80.Z80##n >> 16) + #define DRR16H(n) (drZ80.Z80##n >> 24) + #define DRR16L(n) ((drZ80.Z80##n >> 16) & 0xff) + s->m.a = DRR8(A); s->m.f = drZ80.Z80F; + s->m.b = DRR16H(BC); s->m.c = DRR16L(BC); + s->m.d = DRR16H(DE); s->m.e = DRR16L(DE); + s->m.h = DRR16H(HL); s->m.l = DRR16L(HL); + s->a.a = DRR8(A2); s->a.f = drZ80.Z80F2; + s->a.b = DRR16H(BC2); s->a.c = DRR16L(BC2); + s->a.d = DRR16H(DE2); s->a.e = DRR16L(DE2); + s->a.h = DRR16H(HL2); s->a.l = DRR16L(HL2); + s->i = DRR8(I); s->r = drZ80.spare; + s->ix = DRR16(IX); s->iy = DRR16(IY); + s->sp = drZ80.Z80SP - drZ80.Z80SP_BASE; + s->pc = drZ80.Z80PC - drZ80.Z80PC_BASE; + s->halted = !!(drZ80.Z80IF & 4); + s->iff1 = !!(drZ80.Z80IF & 1); + s->iff2 = !!(drZ80.Z80IF & 2); + s->im = drZ80.Z80IM; + s->irq_pending = !!drZ80.Z80_IRQ; + s->irq_vector[0] = drZ80.z80irqvector >> 16; + s->irq_vector[1] = drZ80.z80irqvector >> 8; + s->irq_vector[2] = drZ80.z80irqvector; +#elif defined(_USE_CZ80) + { + const cz80_struc *CPU = &CZ80; + s->m.a = zA; s->m.f = zF; + s->m.b = zB; s->m.c = zC; + s->m.d = zD; s->m.e = zE; + s->m.h = zH; s->m.l = zL; + s->a.a = zA2; s->a.f = zF2; + s->a.b = CZ80.BC2.B.H; s->a.c = CZ80.BC2.B.L; + s->a.d = CZ80.DE2.B.H; s->a.e = CZ80.DE2.B.L; + s->a.h = CZ80.HL2.B.H; s->a.l = CZ80.HL2.B.L; + s->i = zI; s->r = zR; + s->ix = zIX; s->iy = zIY; + s->sp = Cz80_Get_Reg(&CZ80, CZ80_SP); + s->pc = Cz80_Get_Reg(&CZ80, CZ80_PC); + s->halted = !!Cz80_Get_Reg(&CZ80, CZ80_HALT); + s->iff1 = !!zIFF1; + s->iff2 = !!zIFF2; + s->im = zIM; + s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE); + s->irq_vector[0] = 0xff; + } +#endif +} + +int z80_unpack(const void *data) +{ + const struct z80_state *s = data; + if (strcmp(s->magic, "Z80") != 0) { + if (z80_unpack_legacy(data) != 0) + goto fail; + elprintf(EL_STATUS, "legacy z80 state"); + return 0; + } + +#if defined(_USE_DRZ80) + #define DRW8(n, v) drZ80.Z80##n = (u32)(v) << 24 + #define DRW16(n, v) drZ80.Z80##n = (u32)(v) << 16 + #define DRW16HL(n, h, l) drZ80.Z80##n = ((u32)(h) << 24) | ((u32)(l) << 16) + DRW8(A, s->m.a); drZ80.Z80F = s->m.f; + DRW16HL(BC, s->m.b, s->m.c); + DRW16HL(DE, s->m.d, s->m.e); + DRW16HL(HL, s->m.h, s->m.l); + DRW8(A2, s->a.a); drZ80.Z80F2 = s->a.f; + DRW16HL(BC2, s->a.b, s->a.c); + DRW16HL(DE2, s->a.d, s->a.e); + DRW16HL(HL2, s->a.h, s->a.l); + DRW8(I, s->i); drZ80.spare = s->r; + DRW16(IX, s->ix); DRW16(IY, s->iy); + drz80_load_pcsp(s->pc, s->sp); + drZ80.Z80IF = 0; + if (s->halted) drZ80.Z80IF |= 4; + if (s->iff1) drZ80.Z80IF |= 1; + if (s->iff2) drZ80.Z80IF |= 2; + drZ80.Z80IM = s->im; + drZ80.Z80_IRQ = s->irq_pending; + drZ80.z80irqvector = ((u32)s->irq_vector[0] << 16) | + ((u32)s->irq_vector[1] << 8) | s->irq_vector[2]; + return 0; +#elif defined(_USE_CZ80) + { + cz80_struc *CPU = &CZ80; + zA = s->m.a; zF = s->m.f; + zB = s->m.b; zC = s->m.c; + zD = s->m.d; zE = s->m.e; + zH = s->m.h; zL = s->m.l; + zA2 = s->a.a; zF2 = s->a.f; + CZ80.BC2.B.H = s->a.b; CZ80.BC2.B.L = s->a.c; + CZ80.DE2.B.H = s->a.d; CZ80.DE2.B.L = s->a.e; + CZ80.HL2.B.H = s->a.h; CZ80.HL2.B.L = s->a.l; + zI = s->i; zR = s->r; + zIX = s->ix; zIY = s->iy; + Cz80_Set_Reg(&CZ80, CZ80_SP, s->sp); + Cz80_Set_Reg(&CZ80, CZ80_PC, s->pc); + Cz80_Set_Reg(&CZ80, CZ80_HALT, s->halted); + Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1); + Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2); + zIM = s->im; + Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE); + return 0; + } +#endif + +fail: + elprintf(EL_STATUS|EL_ANOMALY, "z80_unpack failed"); + z80_reset(); + z80_int(); + return -1; +} + +void z80_exit(void) +{ +} + +void z80_debug(char *dstr) +{ +#if defined(_USE_DRZ80) + sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE); +#elif defined(_USE_CZ80) + sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", (unsigned int)(CZ80.PC - CZ80.BasePC), CZ80.SP.W); +#endif +} diff --git a/waterbox/picodrive/platform/base_readme.txt b/waterbox/picodrive/platform/base_readme.txt new file mode 100644 index 0000000000..c37ed0373e --- /dev/null +++ b/waterbox/picodrive/platform/base_readme.txt @@ -0,0 +1,491 @@ +# +PicoDrive 1.xx + +About +----- +#include "../README" + +How to make it run +------------------ + +#ifdef GP2X +Extract all files to some directory on your SD and run PicoDrive.gpe from your +GP2X/Wiz/Caanoo menu. The same .gpe supports GP2X F100/F200, Wiz and Caanoo, +there is no need to use separate versions. +Then load a ROM and enjoy! ROMs can be in .smd or .bin format and can be zipped. +Sega/Mega CD images can be in ISO/CSO+MP3/WAV or CUE+BIN formats (read below +for more details). +#endif +#ifdef GIZ +First make sure you have homebrew-enabled Service Pack installed. Then copy +PicoDrive.exe and KGSDK.dll to any place in your filesystem (both files must +be in the same directory) and run PicoDrive.exe using the launcher of your choice +(some of them might require renaming PicoDrive.exe to Autorun.exe, placing it in +the root of SD, etc). Then load a ROM and enjoy! ROMs can be placed anywhere, can +be in .smd or .bin format and can be zipped (one ROM per zip). +#endif +#ifdef PSP +If you are running a custom firmware, just copy the whole PicoDrive directory to +/PSP/GAME or /PSP/GAMEXXX directory in your memory stick (it shouldn't matter +which one GAME* directory to use). + +If you are on 1.5, there is a separate KXploited version for it. +#endif +#ifdef PANDORA +Just copy the .pnd to /pandora/menu or /pandora/desktop. +#endif + +This emulator has lots of options with various tweaks (for improved speed mostly), +but it should have best compatibility in it's default config. If suddenly you +start getting glitches or change something and forget what, use "Restore defaults" +option. + + +How to run Sega/Mega CD games +----------------------------- + +To play any CD game, you need BIOS files. These files must be copied to +#ifdef PANDORA +/pandora/appdata/picodrive/ directory +(if you run PicoDrive once it will create that directory for you). +#else +the same directory as PicoDrive files. +#endif +Files can be named as follows: + +US: us_scd1_9210.bin us_scd2_9306.bin SegaCDBIOS9303.bin +EU: eu_mcd1_9210.bin eu_mcd2_9303.bin eu_mcd2_9306.bin +JP: jp_mcd1_9112.bin jp_mcd1_9111.bin +these files can also be zipped. + +The game must be dumped to CUE+BIN or CUE+ISO format. +ISO/CSO+MP3/WAV is also supported, but may cause problems. +When using CUE/BIN, you must load .cue file from the menu, or else +the emu will not find audio tracks. + + +Other important stuff +--------------------- + +* Sega/Mega CD: If the background music is missing, the CD image format may be + wrong. Currently .cue/bin is recommended. Be aware that there are lots of bad + dumps on the web, and some use mp3 format for audio, which often causes + problems (see below). +* While iso/mp3 format is supported, it's not recommended to use. + Some of many problems with mp3 are listed below: + * MP3s may be named incorrectly and will not play. + * The game music may play too fast/too slow/out of sync, which means they + are encoded incorrectly. PicoDrive is not a mp3 player, so all mp3s MUST + be encoded at 44.1kHz stereo. +* Sega/Mega CD: If your games hang at the BIOS screen (with planets shown), + you may be using a bad BIOS dump. Try another from a different source, + like dumping it from your own console. +#ifdef GP2X +* What using mp3s, use lower bitrate for better performance (96 or 128kbps + CBRs recommended). +* GP2X F100/F200: When you use both GP2X CPUs, keep in mind that you can't + overclock as high as when using ARM920 only. For example my GP2X when run + singlecore can reach 280MHz, but with both cores it's about 250MHz. When + overclocked too much, it may start hanging and producing random noise, or + causing ARM940 crashes ("940 crashed" message displayed). +* GP2X F100/F200: Due to internal implementation mp3s must not be larger that + 12MB (12582912 bytes). Larger mp3s will not be fully loaded. +#endif + + +Configuration +------------- + +@@0. "Save slot" +This is a slot number to use for savestates, when done by a button press outside +menu. This can also be configured to be changed with a button +(see "key configuration"). + +@@0. "Frameskip" +How many frames to skip rendering before displaying another. +"Auto" is recommended. + +@@0. "Region" +This option lets you force the game to think it is running on machine from the +specified region, or just to set autodetection order. Also affects Sega/Mega CD. + +@@0. "Show FPS" +Self-explanatory. Format is XX/YY, where XX is the number of rendered frames and +YY is the number of emulated frames per second. + +@@0. "Enable sound" +Does what it says. You must enable at least YM2612 or SN76496 (in advanced options, +see below) for this to make sense (already done by default). + +@@0. "Sound Quality" +#ifdef PSP +Sound sample rate, affects sound quality and emulation performance. +22050Hz setting is the recommended one. +#else +Sound sample rate and stereo mode. Mono is not available in Sega/Mega CD mode. +#endif + +@@0. "Confirm savestate" +Allows to enable confirmation on savestate saving (to prevent savestate overwrites), +on loading (to prevent destroying current game progress), and on both or none, when +using shortcut buttons (not menu) for saving/loading. + +@@0. "[Display options]" +Enters Display options menu (see below). + +@@0. "[Sega/Mega CD options]" +Enters Sega/Mega CD options menu (see below). + +@@0. "[32X options]" +Enters 32X options menu (see below). + +@@0. "[Advanced options]" +Enters advanced options menu (see below). + +@@0. "Save cfg as default" +If you save your config here it will be loaded on next ROM load, but only if there +is no game specific config saved (which will be loaded in that case). +You can press left/right to switch to a different config profile. + +@@0. "Save cfg for current game only" +Whenever you load current ROM again these settings will be loaded. + +@@0. "Restore defaults" +Restores all options (except controls) to defaults. + + +Display options +--------------- + +#ifndef PANDORA +@@1. "Renderer" +#ifdef GP2X +8bit fast: +This enables alternative heavily optimized tile-based renderer, which renders +pixels not line-by-line (this is what accurate renderers do), but in 8x8 tiles, +which is much faster. But because of the way it works it can't render any +mid-frame image changes (raster effects), so it is useful only with some games. + +Other two are accurate line-based renderers. The 8bit is faster but does not +run well with some games like Street Racer. + +#endif +#ifdef GIZ +This option allows to switch between 16bit and 8bit renderers. The 8bit one is +a bit faster for some games, but not much, because colors still need to be +converted to 16bit, as this is what Gizmondo requires. It also introduces +graphics problems for some games, so it's best to use 16bit one. + +#endif +#ifdef PSP +This option allows to switch between fast and accurate renderers. The fast one +is much faster, because it draws the whole frame at a time, instead of doing it +line by line, like the accurate one does. But because of the way it works it +can't render any mid-frame image changes (raster effects), so it is useful only +for some games. + +#endif +#endif +#ifdef GP2X +@@1. "Tearing Fix" +Wiz only: works around the tearing problem by using portrait mode. Causes ~5-10% +performance hit, but eliminates the tearing effect. + +@@1. "Gamma correction" +F100/F200 only: Alters image gamma through GP2X hardware. Larger values make +image to look brighter, lower - darker (default is 1.0). + +@@1. "Vsync" +This one adjusts the LCD refresh rate to better match game's refresh rate and +starts synchronizing rendering with it. Should make scrolling smoother and +eliminate tearing on F100/F200. +#endif +#ifdef GIZ +@@1. "Scanline mode" +This option was designed to work around slow framebuffer access (the Gizmondo's +main bottleneck) by drawing every other line (even numbered lines only). +This improves performance greatly, but looses detail. + +@@1. "Scale low res mode" +The Genesis/Megadrive had several graphics modes, some of which were only 256 +pixels wide. This option scales their width to 320 by using simple +pixel averaging scaling. Works only when 16bit renderer is enabled. + +@@1. "Double buffering" +Draws the display to offscreen buffer, and flips it with visible one when done. +Unfortunately this causes serious tearing, unless v-sync is used (next option). + +@@1. "Wait for V-sync" +Waits for vertical sync before drawing (or flipping buffers, if previous option +is enabled). Emulation is stopped while waiting, so this causes large performance +hit. +#endif +#ifdef PSP +@@1. "Scale factor" +This allows to resize the displayed image by using the PSP's hardware. The number is +used to multiply width and height of the game image to get the size of image to be +displayed. If you just want to make it fullscreen, just use "Set to fullscreen" +setting below. + +@@1. "Hor. scale (for low res. games)" +This one works similarly as the previous setting, but can be used to apply additional +scaling horizontally, and is used for games which use lower (256 pixel wide) Gen/MD +resolution. + +@@1. "Hor. scale (for hi res. games)" +Same as above, only for higher (320 pixel wide) resolution using games. + +@@1. "Bilinear filtering" +If this is enabled, PSP hardware will apply bilinear filtering on the resulting image, +making it smoother, but blurry. + +@@1. "Gamma adjustment" +Color gamma can be adjusted with this. + +@@1. "Black level" +This can be used to reduce unwanted "ghosting" effect for dark games, by making +black pixels brighter. Use in conjunction with "gamma adjustment" for more effect. + +@@1. "Wait for v-sync" +Wait for the screen to finish updating before switching to next frame, to avoid tearing. +There are 3 options: +* never: don't wait for vsync. +* sometimes: wait only if emulator is running fast enough. +* always: always wait (causes emulation slowdown). + +@@1. "Set to unscaled centered" +Adjust the resizing options to set game image to it's original size. + +@@1. "Set to 4:3 scaled" +Scale the image up, but keep 4:3 aspect, by adding black borders. + +@@1. "Set to fullscreen" +Adjust the resizing options to make the game image fullscreen. +#endif +#ifdef PANDORA +Allows to set up scaling, filtering and vertical sync. +#endif + + +Sega/Mega CD options +-------------------- + +@@2. "CD LEDs" +The Sega/Mega CD unit had two blinking LEDs (red and green) on it. This option +will display them on top-left corner of the screen. + +@@2. "CDDA audio" +This option enables CD audio playback. + +@@2. "PCM audio" +This enables 8 channel PCM sound source. It is required for some games to run, +because they monitor state of this audio chip. + +@@2. "Save RAM cart" +Here you can enable 64K RAM cart. Format it in BIOS if you do. + +@@2. "Scale/Rot. fx" +The Sega/Mega CD had scaling/rotation chip, which allows effects similar to +"Mode 7" effects in SNES. On slow systems like GP2X, disabling may improve +performance but cause graphical glitches. + + +32X options +----------- + +@@3. "32X enabled" +Enables emulation of addon. Option only takes effect when ROM is reloaded. + +#ifdef GP2X +@@3. "32X renderer" +This currently only affects how the Genesis/MD layers are rendered, which is +same as "Renderer" in display options. + +#endif +@@3. "PWM sound" +Emulates PWM sound portion of 32X hardware. Disabling this may greatly improve +performance for games that dedicate one of SD2s for sound, but will cause +missing sound effects and instruments. + +@@3. "Master SH2 cycles" / "Slave SH2 cycles" +This allows underclocking the 32X CPUs for better emulation performance. The +number has the same meaning as cycles in DOSBox, which is cycles per millisecond. +Underclocking too much may cause various in-game glitches. + + +Advanced configuration +---------------------- + +@@4. "Use SRAM/BRAM savestates" +This will automatically read/write SRAM (or BRAM for Sega/Mega CD) savestates for +games which are using them. SRAM is saved whenever you enter the menu or exit the +emulator. + +@@4. "Disable sprite limit" +The MegaDrive/Genesis had a limit on how many sprites (usually smaller moving +objects) can be displayed on single line. This option allows to disable that +limit. Note that some games used this to hide unwanted things, so it is not +always good to enable this option. + +@@4. "Emulate Z80" +Enables emulation of Z80 chip, which was mostly used to drive the other sound chips. +Some games do complex sync with it, so you must enable it even if you don't use +sound to be able to play them. + +@@4. "Emulate YM2612 (FM)" +This enables emulation of six-channel FM sound synthesizer chip, which was used to +produce sound effects and music. + +@@4. "Emulate SN76496 (PSG)" +This enables emulation of PSG (programmable sound generation) sound chip for +additional effects. + +Note: if you change sound settings AFTER loading a ROM, you may need to reset +game to get sound. This is because most games initialize sound chips on +startup, and this data is lost when sound chips are being enabled/disabled. + +@@4. "gzip savestates" +This will always apply gzip compression on your savestates, allowing you to +save some space and load/save time. + +@@4. "Don't save last used ROM" +This will disable writing last used ROM to config on exit (what might cause SD +card corruption according to DaveC). + +@@4. "Disable idle loop patching" +Idle loop patching is used to improve performance, but may cause compatibility +problems in some rare cases. Try disabling this if your game has problems. + +@@4. "Disable frame limiter" +This allows games to run faster then 50/60fps, useful for benchmarking. + +#ifdef GP2X +@@4. "Use ARM940 core for sound" +F100/F200: This option causes PicoDrive to use ARM940T core (GP2X's second CPU) +for sound (i.e. to generate YM2612 samples) to improve performance noticeably. +It also decodes MP3s in Sega/Mega CD mode. + +#endif +@@4. "Enable dynarecs" +This enables dynamic recompilation for SH2 and SVP CPU code, +what improves emulation performance greatly. + + +Key configuration +----------------- + +Select "Configure controls" from the main menu. Then select "Player 1" and you will +see two columns. The left column lists names of Genesis/MD controller buttons, and +the right column your handheld ones, which are assigned. + +There is also option to enable 6 button pad (will allow you to configure XYZ +buttons), and an option to set turbo rate (in Hz) for turbo buttons. + + +Cheat support +------------- + +To use GG/patch codes, you must type them into your favorite text editor, one +per line. Comments may follow code after a whitespace. Only GameGenie and +Genecyst patch formats are supported. +Examples: + +Genecyst patch (this example is for Sonic): + +00334A:0005 Start with five lives +012D24:0001 Keep invincibility until end of stage +009C76:5478 each ring worth 2 +009C76:5678 each ring worth 3 +... + +Game Genie patch (for Sonic 2): + +ACLA-ATD4 Hidden palace instead of death egg in level select +... + +Both GG and patch codes can be mixed in one file. + +When the file is ready, name it just like your ROM file, but with additional +.pat extension, making sure that case matches. + +Examples: + +ROM: Sonic.zip +PATCH FILE: Sonic.zip.pat + +ROM: Sonic 2.bin +PATCH FILE: Sonic 2.bin.pat + +Put the file into your ROMs directory. Then load the .pat file as you would +a ROM. Then Cheat Menu Option should appear in main menu. + + +What is emulated? +----------------- + +Genesis/MegaDrive: +#ifdef PSP +main 68k @ 7.6MHz: yes, FAME/C core +z80 @ 3.6MHz: yes, CZ80 core +#else +main 68k @ 7.6MHz: yes, Cyclone core +z80 @ 3.6MHz: yes, DrZ80 core +#endif +VDP: yes, except some quirks and modes not used by games +YM2612 FM: yes, optimized MAME core +SN76489 PSG: yes, MAME core +SVP chip: yes! This is first emu to ever do this. +Some in-cart mappers are also supported. + +Sega/Mega CD: +#ifdef PSP +another 68k @ 12.5MHz: yes, FAME/C too +#else +another 68k @ 12.5MHz: yes, Cyclone too +#endif +gfx scaling/rotation chip (custom ASIC): yes +PCM sound source: yes +CD-ROM controller: yes (mostly) +bram (internal backup RAM): yes + +32X: +2x SH2 @ 23MHz: yes, custom recompiler +Super VDP: yes +PWM: yes + + +Problems / limitations +---------------------- + +#ifdef PSP +* SVP emulation is terribly slow. +#endif +* Various VDP modes and quirks (window bug, scroll size 2, etc.) are not + emulated, as very few games use this (if any at all). +* The emulator is not 100% accurate, so some things may not work as expected. +* The FM sound core doesn't support all features and has some accuracy issues. + + +Changelog +------- + +#include "../ChangeLog" + + +Credits +------- + +This emulator is made of the code from following people/projects: + +#include "../AUTHORS" + + +License +------- + +This program and it's code is released under the terms of MAME license: +#include "../COPYING" + +SEGA/Genesis/MegaDrive/SEGA-CD/Mega-CD/32X are trademarks of +Sega Enterprises Ltd. + diff --git a/waterbox/picodrive/platform/game_def.cfg b/waterbox/picodrive/platform/game_def.cfg new file mode 100644 index 0000000000..f4faebdd7a --- /dev/null +++ b/waterbox/picodrive/platform/game_def.cfg @@ -0,0 +1,166 @@ +# +# Sega/Mega CD games +# + +[CD|GM MK-4432 -00|U|ADVENTURES OF BA] +Scale/Rot. fx (slow) = 1 +Better sync (slow) = 1 + +[CD|GM T-60055-00|U|AH3-THUNDERSTRIKE] +Scale/Rot. fx (slow) = 1 + +[CD|GM MK-4401 -00|U|BATMAN RETURNS] +Scale/Rot. fx (slow) = 1 + +[CD|GM T-115075-00|U|BCRACERS] +Scale/Rot. fx (slow) = 1 + +[CD|GM MK-4402|U|COBRA COMMAND] +Better sync (slow) = 1 + +[CD|GM T-121015-00|U|DRAGONS LAIR] +Renderer = 16bit accurate + +[CD|GM T-60094|J|JAGUAR XJ220] +Renderer = 16bit accurate + +[CD|GM T-127015-00|U|LUNAR] +Scale/Rot. fx (slow) = 1 + +[CD|GM T-111065 -0|U|MAD DOG II THE LOST GOLD] +Renderer = 16bit accurate + +[CD|GM T-11105 -00|U|MAD DOG MCCREE] +Renderer = 16bit accurate + +[CD|GM T-81025-00|U|MORTAL KOMBAT] +Renderer = 16bit accurate +Better sync (slow) = 1 + +[CD|GM T-04903-01|U|NIGHT TRAP] +Renderer = 16bit accurate + +[CD|GM T-113025-00|U|NOVASTORM] +Better sync (slow) = 1 + +[CD|GM T-127035-00|U|Popful MAIL] +Better sync (slow) = 1 + +[CD|MK 4603-50|JUE|ROAD AVENGER] +Renderer = 16bit accurate +Better sync (slow) = 1 + +[CD|GM T-50085|U|ROAD RASH] +Renderer = 16bit accurate +Better sync (slow) = 1 + +[CD|GM MK-4416 -00|E|ROBO ALESTE] +Renderer = 16bit accurate + +[CD|GM T-06201-03|U|SEWER SHARK] +Renderer = 16bit accurate + +[CD|GM T-113045-00|E|SHADOW OF THE BEAST TWO] +Renderer = 16bit accurate + +[CD|GM MK-4404|U|SOL-FEACE] +Better sync (slow) = 1 + +[CD|GM MK-4407-00|E|SONIC THE HEDGEHOG-CD] +Scale/Rot. fx (slow) = 1 + +[CD|GM MK-4407 -00|U|SONIC THE HEDGEHOG-CD] +Scale/Rot. fx (slow) = 1 + +[CD|GM T-22025-00|U|THE 3RD WORLD WAR] +Better sync (slow) = 1 + +[CD|GM MK- 4430 -|E|YUMEMI MISTERY MANSION] +Renderer = 16bit accurate + +# +# Virtua Racing +# +[MD|GM MK-1229 -00|U|Virtua Racing] +Renderer = 8bit fast +Show FPS = 1 +GP2X CPU clocks = 235 + +[MD|GM G-7001 -00|J|Virtua Racing] +Renderer = 8bit fast +Show FPS = 1 +GP2X CPU clocks = 235 + +[MD|GM MK-1229 -00|E|Virtua Racing] +Renderer = 8bit fast +Show FPS = 1 +GP2X CPU clocks = 235 + +[MD|GM MK-1229 -00|E|VIRTUA RACING \00\00\00\00\00\00\00\00\00] +Renderer = 8bit fast +Show FPS = 1 +GP2X CPU clocks = 235 + +# +# Genesis/MegaDrive games +# +[MD|GM MK-1029-00|E| BURNING FORCE] +Renderer = 16bit accurate + +[MD|GM T-14023 -00|J| BURNING FORCE] +Renderer = 16bit accurate + +[MD|GM T-14026 -00|U| BURNING FORCE] +Renderer = 16bit accurate + +[MD|GM T-95076-00|U|CASTLEVANIA BLOODLINES] +Renderer = 16bit accurate + +[MD|GM T-95076-00|E|CASTLEVANIA THE NEW GENERATION] +Renderer = 16bit accurate + +[MD|GM MK-1569 -50|A|COMIX ZONE] +Renderer = 16bit accurate + +[MD|GM G-4132 -00|1|] +Renderer = 16bit accurate + +[MD|GM MK-1569 -00|4|COMIX ZONE] +Renderer = 16bit accurate + +[MD|GM T-097116 00|4|MORTAL KOMBAT 3] +Renderer = 16bit accurate + +[MD|GM G-4119-00|J| OUT_RUNNERS 1994/03/03 Ver.FINAL!!] +Renderer = 16bit accurate + +[MD|GM T-13096-00|U| OUT_RUNNERS] +Renderer = 16bit accurate + +[MD|GM T-48376 00|JUE|RED-ZONE] +Renderer = 16bit accurate + +[MD|GM T-177016-00|F|STREET RACER] +Renderer = 16bit accurate + +[MD|GM T-95043-00|J|] +Renderer = 16bit accurate + +[MD|GM T-25036 -00|U| SHOVE IT!] +Renderer = 16bit accurate + +[MD|GM MK-1104 -00|U|AFTER BURNERII] +Renderer = 16bit accurate + +[MD|GM T-32053 -00|U|ARCUS ODYSSEY] +Renderer = 16bit accurate + +[MD|GM 00054010-00|JUE|RAMBO \87V] +Renderer = 16bit accurate + +[MD|GM 00054010-01|JUE|RAMBO \87V] +Renderer = 16bit accurate + +[MD|GM T-50406 -01|U|GALAHAD] +Renderer = 16bit accurate +